Is there possible to check if previous_def exists? to avoid the code raise exception.
def meth
previous_def
# ...
end
# Raise: Error: there is no previous definition of 'meth'
What is the equivalent of BASH exec in Crystal? same in Ruby is Kernel#exec.
╰─ $ \cat 1.sh
exec sleep 100
╰─ $ sh 1.sh &
[1] 95600
╰─ $ ps aux |grep 1.sh
╰─ $ ps aux |grep sleep
zw963 95600 0.0 0.0 8608 960 pts/1 S 02:19 0:00 sleep 100
The following code not raise a error on compile-time, i consider check use a missing defined const is possible, right? for following code, what i expected is, raise a exception to tell me use a not defined const.
class A
def meth
MissingClass.new
end
end
a = A.new
# no error
Is there a way to make #try chainable?
class A
def meth1
nil
end
end
a = A.new
p a.try &.meth.upcase.downcase
Above code raise following exception.
In 1.cr:10:16
10 | p a.try &.meth.upcase
^-----
Error: undefined method 'upcase' for Nil
But, what i expected is, it only return nil with no exception raised.
The key point is, if the first meth1 is nil, all latter should be skipping.
In fact, Dart use this hack. check this:
EDIT: In fact, is there a more simpler way to use #try make following code work?
y = if rand > 0.5
[[1, 2, 3]]
else
nil
end
y.first.each do |e|
p e
end
# Error: undefined method 'first' for Nil (compile-time type is (Array(Array(Int32)) | Nil))
Following code is work, but too verbose.
y.try do |e1|
e1.first.try do |e2|
e2.each do |e|
p e
end
end
end
Probably depends on the exact context. What are you wanting to do?
Process.exec
You never call #meth, so the compiler tree shakes it out of the compiled binary. This is, IMO, why tests are still important in Crystal. Otherwise it would be possible for an end user to go use a method of your library and find it fails due to a typo/bug in the method. If that method had test coverage, you would have found it earlier.
Wouldn’t this just be a.try &.meth1.try &.upcase.downcase?
y = if rand > 0.5
[[1, 2, 3]]
else
nil
end
y.try &.first.each do |e|
p e
end
Never mind, what i expect is, write a method, invoke previous_def if available, but if previous def is not exists, no raise error.
But, it is a not defined const, we can even visit the the const in macro at the compile time.
so, i guess it should be possible to find this const missing at compile time?
Sorry, above example doesn’t express what I mean.
y = if rand > 0.5
if rand > 0.5
[[1, 2, 3]]
else
[nil]
end
else
nil
end
# following example not work.
y.try &.first.each do |e|
p e
end
Right, because in this case the .try on y ensures y doesn’t return nil. But then the .first call returns Nil | Array(Int32), so it fails. You’d have to add another .try on the response of .first to handle that. I.e. y.try &.first.try &.each. Of course there are other ways to handle nil that could make this more readable. E.g. maybe something like:
Well in this case it is being used, even if your local x variable isn’t. I guess there are just certain exceptions/limitations in what the compiler is able to safely ignore.
To type x = ->meth the compiler needs to know what’s the type of meth. And that’s where it’s typed and the constant is checked and the error is produced.
So maybe the explanation isn’t “when the method is unused” but “when the method doesn’t need to be typed” (that usually means it’s unused)