在各种讨论中,建议允许使用如下语法:
if x then y
作为一个简短的“if”语句和通用的替代:
x && y
利用短路&&
运算符有条件地执行y
的语法(其中y
通常包含其他副作用,不一定返回Bool
)。
这个if-then
结构的主要优点是:更易读的代码,更少依赖滥用&&
,并且正式包含不需要end
的“if”语句形式关键词。
前几天我突然想到,这种语法也可以提供一种方便的方法来实现#550,它看起来像:
A = [if x % 2 == 0 then f(x) for x in 1:10]
依靠if-then
不需要end
关键字这一事实,即使我们使用 python 样式的守卫,我们也可能需要某种形式的关键字:
A = [f(x) for x in range(10) if x % 2 == 0]
需要明确的是,Julia 守卫语法本质上是从以下内容进行重写:
A = [if x % 2 == 0 then f(x) for x in 1:10]
到
A = [Filter(x->x % 2 == 0, f(x) for x in 1:10)]
同样作为澄清说明,这将允许在 _generator_ 级别而不是仅在 _comprehension_ 级别(这与 python 允许的内容相匹配)的保护语法。
Perl/Ruby 风格的 if/for 修饰符语法似乎会更好地与此混合。 换句话说:
println("positive") if x > 0 # conditional execution
x^2 for x=1:100 # generator
[ x^2 for x=1:100 ] # comprehension
x^2 if x % 3 == 0 for x = 1:100 # filtered generator
[ x^2 if x % 3 == 0 for x = 1:100 ] # filtered comprehension
它还具有在其他语言中具有先例的好处,而没有end
语法的if
- then
似乎没有。
只是关于问题管理的一个旁注:#6823 正是讨论了这个问题。 在某些时候它被关闭而没有评论,我跟进询问它为什么被关闭,因为显然没有达成共识来关闭它,但从未得到答复。 似乎不关闭 #6823 之类的问题会更有效,否则这些讨论将只是循环往复,并且将再次重复原始问题中的所有要点。 在某些时候更改#6823 的标题可能是有意义的,然后在此处添加。
是的,好点。 事实上,#6823 似乎是在讨论中,可能不应该被关闭。
也许我是少数,因为其他语言也采用了这种方法,但我总是发现条件之前的动作真的很奇怪,例如println("positive") if x > 0
。 我想它比if x > 0 println("positive") end
更简洁,但至少对我来说它是以可读性为代价的。
我把它想象成一个对话:
朱莉娅:“我要打印一个字符串……”
哈罗德:“太棒了!”
朱莉娅:“……但前提是满足某些条件。”
哈罗德:“哦。:(”
相对
Julia:“如果满足某些条件,我会打印一个字符串。”
哈罗德:“好吧,很酷。”
@ararslan :我不反对,这是尽管 Ruby 和 Perl 中的现有技术,但此功能不在 Julia 中的原因之一。 但是,它确实与生成器和推导的for
修饰符语法混合得更好,这就是我在这里提出它的原因。
@StefanKarpinski是的,同意,它确实与这些更吻合。 我仍然无可救药地依附于行动之前的条件。 :smile: (但正如我发现自己最近经常说的那样,我的意见并不重要;我只是一个人。)
我想如果你有类似的东西
if x % 3 == 0 then x^2 for x = 1:100
那么并不清楚您正在启动一个理解/生成器/thingamajig,因为它也读起来好像可以像这样分组
if x % 3 == 0 then (x^2 for x = 1:100)
即,如果某些条件则生成器。 我不介意
if x % 3 == 0 x^2 end for x = 1:100 # More obvious what's happening, IMO
filter(x -> x % 3 == 0, [x^2 for x = 1:100]) # Verbose, but... ¯\_(ツ)_/¯
我想如果条件是遵循生成器中的操作,我想我更喜欢与if
不同的关键字,例如where
。 然后它读起来几乎就像一个 SQL 查询,例如
x^2 for x = 1:100 where x % 3 == 0
我认为where
for
比if
过滤x
的值更清楚一点。
对我来说,让数据流向单一方向似乎更好,尽管在这种情况下从右到左而不是从左到右。
你能详细说明你的意思吗?
for 1:n
“生成”值, if x % 3 == 0
过滤它们, x^2
转换它们——生成器已经从右到左流动,为了保持这种流动,过滤器需要进入中间。 如果if
子句位于for
子句的右侧,那么数据会从中间“流动”到最右边,然后到最左边,这很奇怪。 如果if
子句在左侧,则数据从最右侧“流动”到最左侧到中间。 我知道 SQL 把where
子句放在表名的右边,把表达式放在左边——因为这读起来更像英语——但我一直觉得这读起来很烦人,我认为读起来像英语不是在编程语言设计中应该采取的启发式方法。
我不喜欢if x then y
的事情:
then
关键字。if x y end
if x then y
更短; x && y
甚至更短。then
关键字在语言中广泛用于完全相反的语法:多行if
语法需要end
关键字(或 bash 中的fi
,呸)。哦,是的,我明白你现在关于流量的意思了。 这就说得通了。 感谢您的解释!
能做会不会很奇怪
x^2 if x % 3 == 0 for x = 1:100
并且_不能_做
println("positive") if x > 0
?
所有的好点。
我真的很喜欢@StefanKarpinski在他的第一条评论中首次提出的语法。 我主要对条件生成器感兴趣,并以更通用的短格式 _if_-form 作为奖励。
关于生成器,我正在阅读if
(或where
- 我对此没有意见)作为范围的一部分......它正在创建一个迭代器x = 1:10 if/where x % 2 == 0
,它然后与左侧的表达式组合以创建一个数组(或生成器)。
从某种意义上说, x = 1:10 where x % 2 == 0
本身就是某种可迭代对象的生成器。 这可能是独立的语法,不是吗?
我觉得过滤在某种程度上是与条件if a then b
语句不同的操作。 过滤作用于迭代范围。 当if a then b
与生成器左侧的表达式结合时,我希望它在a
为false
的情况下发出nothing
#$ 。 比较如果我添加括号,逻辑上会发生什么:
[(x^2 if i % 2 == 1) for i = 1:10] # [nothing, 4, nothing, 16, nothing, 36, nothing, 64, nothing, 100]
[x^2 (for i = 1:10 where i % 2 == 0)] # [4, 16, 36, 64, 100]
以@ararslan为例,如果我们允许的话
println("positive") if x > 0
然后恕我直言,它遵循
x^2 if x % 3 == 0 for x = 1:100
应该可能发出nothing, nothing, 9, nothing, nothing, 36, ...
最后,如果我们要采用简写if
条件,我的投票是声明之前的条件,原因在@ararslan的第一篇文章中概述 - 是阅读代码时最不意外的原则。 (请记住,如果他们说代码的阅读量多于编写量,那么if a then b
的语法比a && b
更好,即使后者更短)。 这也意味着生成器内的两种可能的if
类型将是不同的 - 在最左边 - 与表达式 - 或在最右边 - 与范围。
至于 Ruby/Perl 的传统,我觉得最好尝试提出最好的解决方案,而不是被传统所束缚。 如果它有效并且感觉自然,人们会喜欢它。
此外,如果我们在范围中有if/where
,我们是否需要小心确保范围对于多维生成器保持笛卡尔坐标?
# Make a circular array (filled with distance to center)
r = 5
[sqrt(x^2 + y^2) for x = -5:5, y = -5:5 where x^2 + y^2 <= r^2]
这有点酷,有点可怕!
我觉得过滤在某种程度上是与条件 if a then b 语句不同的操作。
是的! 我正要发表同样的评论。 过滤作为一个整体对迭代器进行操作,而不是内部计算表达式的一部分。
我也和@andyferris的感觉一样,表达式和迭代之间的if
似乎“转换”了表达式的值而不是迭代的形状,并且应该产生nogthing
时不满足条件(但我可能被 python/haskell 理解宠坏了)。
显然,当不在生成器表达式的上下文中时, x if false
将评估为nothing
。 支持[x^2 if x % 3 == 0 for x=1:100]
而不是x if y
本身是完全合理的。
就个人而言,如果只有一个语句,我宁愿能够省略end
。
if length(A) != length(B) throw(ArgumentError("..."))
如果没有end
,那么它可以假设只有一个表达式。 我猜这之前已经详细讨论过了?
我注意到我不希望在条件之后使用分号 - 在表达式之后......_也许_......虽然我不喜欢它。
我宁愿这样,也不愿为类似形式的 if 语句使用两种不同的语法; _(编辑: if x; ...; end
和if x then; ...
。if condition then action
在我身上长大了。)_
支持 [x^2 if x % 3 == 0 for x=1:100] 但不支持 x if y 本身是完全合理的。
@StefanKarpinski我完全同意这一点。 然而...
如果 if 子句在左侧,则数据从最右侧“流动”到最左侧到中间。
我将x^2 if x % 2 == 0 for x in 1:10
读为x^2 where x % 2 == 0 for each x in 1:10
,因为它是理解性的,所以对我来说很有意义; 你对转型最感兴趣。
在 SQL 查询中,同样的观点是正确的,不是吗?
因此,我不认为将“生成器”作为阅读它的起点是完全正确的,_for a comprehesion_。 另一方面,一个 for 循环......这更有意义。
就个人而言,如果只有一个语句,我宁愿能够省略 end 。
我很久以前就提出了这个,但没有得到任何支持: https://github.com/JuliaLang/julia/issues/1657。 这实际上是一个相对无破坏性的更改,因为看到一些这样的编写代码会很奇怪而且很少见:
if cond body
end
您如何看待使用do
块而不是then
? 即: if x do y end
只是一个小小的旁注:我看不出有任何方法可以在没有成熟的 julia 解析器的情况下在编辑器中正确处理if x y
本身(即在生成器之外),因为您需要能够确定有多少令牌跟随if
。 我正在考虑 vim,但我想其他编辑器可能处于同样的情况。 y if x
可能也是如此,但我不确定(完全披露:我也很不喜欢y if x
本身;我原则上并不反对if x y
但认为对于人类来说也可能有点难以解析,不仅是编辑)。
@diegozea我认为同样的问题。 我还是更喜欢if x y
。
@carlobaldassi您可以做一些事情来使人类更容易解析。
您可以强制该单语句 ifs 在条件和表达式之间没有换行符。
不过,我不确定我是否愿意被迫在长时间的表达中这样做。
或者,如果条件后有换行符,则可以强制表达式后有换行符; 因此,以下内容不会编译,但当然会给出明确的错误消息:
if length(A) != length(B)
throw(ArgumentError("lengths must match")
if some_condition(A, B)
N *= 2
但是,这将:
if length(A) != length(B) throw(ArgumentError("lengths must match")
if some_condition(A, B) N *= 2
这将:
if length(A) != length(B)
throw(ArgumentError("lengths must match")
if some_condition(A, B)
N *= 2
这也可以防止你犯这种错误:
if is_present(x)
y = 2 * x[]
return y * 2
我认为if x then y
仍然胜过任何其他语法的最大论点是可读性。 if x y end
、 if x y
或x && y
更短在我的书中是无关紧要的(除了我们谈论的是微不足道的 1-5 个字符差异),因为这些都不是几乎和if x then y
一样清晰。 它还避免了编辑器解析问题或可能破坏过去代码。 对于短 if 语句来说,这只是一个不错的、干净的、简短的语法。
但是,我确实认识到在生成器案例中使用if-then
的潜在混淆; 鉴于此,我同意
x^2 if x % 3 == 0 for x = 1:100 # filtered generator
[ x^2 if x % 3 == 0 for x = 1:100 ] # filtered comprehension
是最清楚的,认识到表达结构是
generated_value_expr value_generator_expr => generator_expression
[generator_filter_expr] for_generator_expr => value_generator_expr
即generator_filter_expr
直接应用于从for_generator_expr
生成的值,然后将未过滤的值传递给generated_value_expr
。
我认为这里的区别很重要,因为它不是允许的相同逻辑
println("positive") if x > 0
TL;DR:我们应该有x^2 if x % 3 == 0 for x = 1:100
过滤生成器,但相同的语法逻辑不适用于println("hey") if x > 0
,因此,我们仍然应该考虑if x then y
短格式if 语法。 尽管显然这里的两个想法现在完全不相关。
@H-225 这对我来说似乎很奇怪并且最终不是朱利安,特别是在没有end
的新行上采取行动。
对于编辑器来说,解析仍然是一场噩梦,因为编辑器(如 Vim)不在乎什么是条件或动作,什么不是条件或动作——事实上,如果没有 Julia 解析器,他们无法知道——而是他们关心诸如if
和end
之类的东西的位置。 我认为让 Vim 认识到在那种情况下不需要end
是非常困难的。 我意识到让编辑更容易不是设计决策的好论据,我只是说。
绝对 :-1: 来自我的if x y
。 我更喜欢if x then y
,因为我的小大脑更容易解析。 :stuck_out_tongue_winking_eye:
是否有理由不简单地将三元问号运算符也用于 if 语句? 您已经可以通过这样做来模仿 if 语句
condition ? if_condition_true_eval_expr : nothing
为什么不这样做,如果你不包含冒号,那么它就是一个 if 语句,那么你就会有
condition ? if_condition_true_eval_expr
这样你就不必引入任何新的关键字,这行得通吗?
@esproff有趣的是,我打算提出相反的建议:将这个 julep 中的 if-then 想法扩展到单行 if-then-else 表达式
if cond then a else b
else 子句是可选的。 它甚至可能低于cond ? b : c
。 对我来说,这一切都是为了摆脱 C 风格的三元组,转向更易于阅读的代码。 (我之前肯定使用过condition ? a : nothing
- 这似乎是一个 hack(因为它是, nothing
出于某种模糊的原因很重要)并且其他人阅读时会感到困惑)。
但是,当然,为什么我们不能同时拥有所有这些想法呢?
@andyferris是的,这是另一种 Pythonic 方式。 我想这取决于你想变得多么简洁,数学家通常似乎很喜欢简洁,但老实说,只要我不必使用笨重的东西,我都会很高兴
if condition; eval_expr; end
但老实说,我会很高兴,只要我不必使用笨重的
if condition; eval_expr; end
的确!
对于它的价值,我喜欢 x && y 符号并且不认为它是一种滥用。
我个人更喜欢基于运算符的解决方案,如果第一条语句为假,则不返回false
。 尽管我喜欢将a ?: b
作为三元运算符的两个参数版本,但我几乎可以处理任何事情。
?
的想法在 #6823 中得到了相当广泛的讨论,可能值得重新阅读该讨论。
我从那次讨论中来到这里,但认为这是一个更好的发表评论的地方。 我认为if a then b
和仅使用?
而不使用:
都会有些混乱,但只要它们提供相同的功能就不会抱怨。
我同意@EricForgy。 也许我现在只是习惯了它们,但对我来说,以这种方式使用&&
和||
对 Julia 来说是惯用的,特别是对于错误检查(例如x || throw(y)
)。 它们看起来一点也不模棱两可或难以理解。 另外,我真的不明白为什么如果x
为 false 时x && y
返回false
x
很重要,因为无论如何它可能不应该在函数末尾使用,它会影响函数的返回值。
C 风格的三元组非常普遍。 我认为不只是数学家重视这种语法。 我能想到的唯一一种具有三元组但不支持 C 风格的语言是 Python,而 FWIW 我鄙视 Python 三元组。 只要您使用空格并尊重行长, condition ? action1 : action2
就既紧凑又可读。 对于更长的条件和动作,应该使用
if condition
somelongaction1
else
somelongaction2
end
无论如何为了可读性。
关于then
,本次讨论的重点,FWIW 我可能不会使用它,即使它已实现,因为再次, &&
和||
对我来说是惯用的。 虽然我会在if x y
、 x ? y
或x ? y : nothing
的心跳中服用then
x ? y : nothing
。
就个人而言,我更喜欢y if x
。 它可能看起来是错误的方式,但除了 Ruby 和 Perl 之外还有优先级:数学案例语法有这种方式
我不_喜欢_为此使用&&
或||
,因为我从不记得x && y = z
没有按照我期望的方式解析。 我认为它比y if x
具有更高的认知负荷; 这也适用于if x y
。
IMO, x ? y
_smells_ 就像一个语法错误,不管它是否真的有效。
x ?? y
也许? x ?: y
是一个 GNU C 扩展,意思是x ? x : y
,所以??
和?:
可能是&&
和||
的低优先级版本
我的偏好顺序: y if x
== x ?? y
< if x then y
< x && y
< x ? y
< if x y
。
FWIW。 我更喜欢用?
、 &&
和||
将代码简洁明了地分开,尽管cond ? expr
语法可能比&&
更清晰
我确实喜欢经常做goodcondition || return
类型的流程,这对于 if 语句来说并不容易。 我不想失去它(或被欺负不使用它)
对于没有:
的三元组,允许没有else
条件的简洁if
/ elseif
块可能会很好:
x==5 ? f1() :
x==6 ? f2()
并且可以想象将其扩展到 switch 类型的语句:
match x:
5 ? f1() :
6 ? f2()
就可读性而言,这取决于。 对于许多简短的条件/动作,它更具可读性(使用干净的间距!!)能够使用清晰的分隔符将条件/动作排列在连续的行上。
对于生成器,我更喜欢where
或when
而不是重新利用if
,因为它是过滤器,而不是条件:
x = [i^2 for i in 1:10 when i%2 == 0]
我认为这意味着x = [i^2 for i in filter(..., 1:10)]
更清楚。
我会注意到,自从讨论这个问题后,我将不再反对if condition then action
- 它是在我身上成长起来的。
朱莉娅确实倾向于更“罗嗦”的一面,有function
和end
等,所以我认为它很适合。不得不在周围加上括号也有点烦人如果您在condition && action
语法之间来回切换表达式。
关于 Perl/Ruby 语法“action if condition”:我真的很喜欢这种语法,虽然我同意它在使用不当时会降低可读性,但我也相信它有时会_增加_可读性。
例如:
throw(DomainError()) if some_condition || some_other_condition && so_on
在阅读“throw domain error if”之后,您已经知道接下来将是对输入的健全性检查。 如果条件的详细信息对您不重要,您可以跳到下一行。
上一句是这种结构在自然语言中如何频繁出现的一个例子。 动作“跳到下一行”首先出现,不太重要的“如果你不感兴趣”出现在从句中。 同样,读者可能无需实际阅读到句子的结尾,就可以大致猜测“如果”一词后面会出现什么。
(如果我能想到的话,我也会给出一个自我参照的例句。)
作为一个 Perl 的老手,我很同情这种语法,但我认为这对于那些没有 Perl 背景的人来说会很难卖。 一个赞成的论点是它与理解中的过滤器语法相匹配。 反对的一个论点是,有一个评估顺序不是从左到右的构造是很奇怪的。 当然,推导也正是如此,所以🤷♂️
对我来说,一个相关的问题是:我们是在泛化分支还是过滤? 这是分支if
语义(和语法)的概括,因此如果该语法已经指示过滤,则为此目的从理解/生成器中借用语法可能是不幸的。
(顺便说一句,我喜欢一些好的过滤语法,比如我们好的.
语法。为了说明我上面的观点,也许map
- filter
可能看起来像f.(a) if g.(a)
f(x) for x in a # lazy map
f(x) for x in a if g(x) # lazy map - filter
x for x in a if g(x) # lazy filter where `f` is `identity`
f.(a) # map / broadcast
f.(a) if g.(a) # like a map/broadcast - filter operation
a if g.(a) # like the above where `f` is implicitly `identity`
[1,2,3] if [true, false, true] == [1, 3] # or something... here we simply make `if` an infix operator for filtering
很抱歉跑题了,我不确定上面是不是一个好主意,但只是指出理解过滤if
语法可能有另一种潜在用法,它具有过滤语义)
最后 - 我有点同意@tbreloff上面的观察......二进制?
是最紧凑的语法(这个线程的重点是制作紧凑的语法),我总是发现if
是生成器过滤的一个有点令人惊讶的选择。
@StefanKarpinski写道:
Perl/Ruby 风格的 if/for 修饰符语法似乎会更好地与此混合。 换句话说:
julia println("positive") if x > 0 # conditional execution x^2 for x=1:100 # generator [ x^2 for x=1:100 ] # comprehension x^2 if x % 3 == 0 for x = 1:100 # filtered generator [ x^2 if x % 3 == 0 for x = 1:100 ] # filtered comprehension
它还具有在其他语言中具有先例的好处,而 if-then without end 语法似乎没有。
这对语法也会更好。
我认为[x^2 if x % 3 == 0 for x = 1:100]
应该是:
[(x^2 if x % 3 == 0) for x = 1:100]
```
Then `for` stay's in infix position which is currently an error. Of course we can change its meaning because of leading `[` but it would not work as generator:
```julia
x^2 if x % 3 == 0 for x = 1:100
我认为
[x^2 if x % 3 == 0 for x = 1:100]
应该是:
那将不是过滤生成器。 当x
为真时, 2 if x
返回2
,但当x
为假时,它也必须返回一些东西; 通常是nothing
。 所以这会给出一个数字数组和什么都没有。 这也是过滤生成器语法中if
必须在for
之后的部分原因。
是的,你是对的。 也许应该这样写:
[for x = 1:100 x^2 if x % 3 == 0]
Afaics,这将是有效的可解析而不使用括号,酷!
只是想...
[ for x = 1:100 if x % 3 == 0 push x^2]
for x = 1:100 if x % 3 == 0 push x^2 # other keyword could be used, e.g. yield
这更类似于自然构造
for x=1:100
if x%3==0
push!(somearray, x^2)
end
end
我刚刚在看别的东西时又看到了这个朱利酒。
我仍然希望像if a then b
单行形式; 我确实发现 julian 替换a && b
即使在使用了几年后也相当难以理解:没有办法直接将其作为英文句子阅读。
我还觉得需要向新手解释a && b
习语有点尴尬,因为我们可以有一个不言而喻的替代语法,而且只需要更长的时间。
只是没有办法直接把它读成英文句子
a && b
读作“a and b”,如“if a then also do b”
a || b
读作“a 或 b”,如“a 必须为真,否则为 b”
我知道它的作用,为了简洁起见,我有时会使用它。 但是尽我所能(如前所述,几年来)我不能将“a和b”视为一个句子。 每次都只是轻微的认知失调。
相比之下,我总是发现“a 或 b”是相当可读的。
有趣的是,这方面的不同方面今天在工作中出现了两次。
早上,我们有一个使用&&
而不是if ... end
的 Julia PR,我指出,作为一名代码阅读器(PR 审阅者),它需要额外的努力(并且很容易错过) 可能会或可能不会执行的分支。 这个例子是a() && b!()
,其中b!
是极度变异的。 (在这种情况下, b!()
移动或删除了文件系统中的文件,这似乎立即很危险,但我的大脑无法完全弄清楚这只有在!a()
和这种情况下才有问题实际上得到了正确的防范)。
下午,另一位软件工程师(不认识 Julia)指出,与朋友说英语时,有时他会回答“是a
还是b
” 回复“是”。 只有他的软件工程师的朋友会明白-其他人就一点都看不懂。 正常人只是不这么想。 🙂 这有点与我的下一点有关(编辑:我应该说,与上面 Stefan 的回应有关,对于许多人来说,我认为他们不会发生这种情况)。
我一直以来对这个问题的立场是,使用&&
(或||
)是一种简短的分支语法,只有具有强大 PL 背景的人才能阅读,即使这样也会添加一些认知/视觉负荷(只是区分&
与&&
)。 我觉得在多学科团队(科学家和软件工程师的混合体)中工作时,半数团队都会感到困惑。 即使作为一名软件工程师,我也觉得我们在逻辑&(::Bool, ::Bool) --> Bool
和分支&&(::Bool, ::Any) --> Any
之间存在奇怪的脱节(是的,后者实际上不是一个函数,但希望你明白我的意思) . 除了类型本身,在 Julia 中,我通常期望前者是“功能性的”,而后一种形式通常涉及潜在的副作用——尤其是在第二个表达式中。
编辑:多想一下,这里的问题完全是关于副作用和程序流程的。 这是很容易让大家理解的是“功能性”的使用&&
是优化&
。 对于非纯表达式,它们完全不同是相对难以调和的。
在某些情况下,我认为if a then b
的“优先级”更清晰:
guard && c += 1 # probably an error because it's parsed as (guard && c) += 1
guard && (c += 1) # parentheses required
if guard then c += 1 # no ambiguity here
编辑器中的语法突出显示也有助于在表达式的开头标记if
。
我已经知道这个讨论一个小时了,如果有人提出这个建议,请原谅我。
在我看来,'&&' 和 '||' 的短路选项之所以使用,是因为我们想要一行中的简单 if 语句,没有分号。 但是短路似乎是一种解决方法,但会产生另一个问题:作为一个普通人,如果没有以前看过它,或者知道第二个表达式仅在必要时才被评估,就很难理解和解析该语法。 不直观的阅读(作为人类)似乎是由于短路的视觉和逻辑缺陷。 甚至似乎在知道它的含义之后,阅读它可能比应该的更难。
如果我没记错的话,这两个问题都可以用一个宏来解决:
@if条件结果
否定可以用 ! 之前的条件,或者一个@ifnot宏。 只是我,还是对计算机没有歧义,对人类来说易于阅读,并且全部在一条线上?
甚至似乎在知道它的含义之后,阅读它可能比应该的更难。
^ 我非常同意这一点。
@if条件结果
您已经可以执行以下操作,看起来几乎相同:
if condition result end
下面是完整的 if-then-else 语法的宏。 但是,由于if
和else
是保留关键字,因此宏使用If
、 Then
和Else
代替。
syntax_error() = error("Valid syntax is either `<strong i="20">@If</strong> cond Then ex` or `<strong i="21">@If</strong> cond Then ex1 Else ex2`")
function If(exprs...)
n_args = length(exprs)
if n_args == 3
if exprs[2] != :Then
syntax_error()
end
ex = quote
if $(exprs[1])
$(exprs[3])
end
end
elseif n_args == 5
if ( exprs[2] != :Then ) || ( exprs[4] != :Else )
syntax_error()
end
ex = quote
if $(exprs[1])
$(exprs[3])
else
$(exprs[5])
end
end
else
syntax_error()
end
return esc(ex)
end
macro If(exprs...)
If(exprs...)
end
foo(x) = <strong i="22">@If</strong> x > 0 Then println("greater than zero") Else println("less than zero")
在这里我们可以看到foo
的作用:
julia> foo(3)
greater than zero
julia> foo(-3)
less than zero
我更喜欢类似的东西
x0 = 1
x1 = 2
x3 = 3 when y>0 # y>0 is evaluated first
x4 = 4
when的优先级低于 = 并且从右到左操作。
您已经可以执行以下操作,看起来几乎相同:
if condition result end
我不知道! 我总是认为那个人需要通常有换行符的分号。 所以就我而言,语法
if condition result end
完全使&&
的使用变得多余,所以没有问题! 我看到一个甚至可以执行以下操作:
if condition result_1 else result_2 end
在这种情况下,添加关键字end
可能比制作宏更容易。 但是感谢您抽出时间来制作它^_^ 在文档中添加单行 if 语句的可能性是一个好主意吗? 我看到如果一个人做?If<enter>
结果已经很多行了......但我觉得这个功能应该更多地宣传。
回顾最初的讨论,我赞成添加“If x then y”,尽管我发现它与“if”的单行版本有点多余。 但是,嘿,编写对您有意义的代码,对吧?
最有用的评论
也许我是少数,因为其他语言也采用了这种方法,但我总是发现条件之前的动作真的很奇怪,例如
println("positive") if x > 0
。 我想它比if x > 0 println("positive") end
更简洁,但至少对我来说它是以可读性为代价的。我把它想象成一个对话:
朱莉娅:“我要打印一个字符串……”
哈罗德:“太棒了!”
朱莉娅:“……但前提是满足某些条件。”
哈罗德:“哦。:(”
相对
Julia:“如果满足某些条件,我会打印一个字符串。”
哈罗德:“好吧,很酷。”