Let's say I have a variable which is one level up, which I just want to query its' value. I have two options:
uplevel { set var_name }
Or:
upvar var_name
If I need to query the variable just once, and not change it, which one should be faster?
You'll find that upvar is probably faster for this. Not necessarily, but most likely. (If you're worried about performance, time the alternatives.)
Note that they will both necessarily have to resolve the variable name; that's a cost that's going to be borne anyway. But the version with upvar doesn't involve moving code between contexts, so it is likely to be faster.
FWIW, when I try with the example below, my intuition is correct. (The key is that one uses the upvar bytecode opcode; the other does invokeStk, which is slower because that's the general command dispatcher and has a bunch of overhead necessary for other purposes.)
% proc foo {y} {set x 1; bar $y}
% proc bar {y} {upvar 1 x x; list $x $y}
% foo 2
1 2
% time {foo 2} 10000
17.8188412 microseconds per iteration
% proc bar {y} {set x [uplevel 1 {set x}]; list $x $y}
% foo 2
1 2
% time {foo 2} 10000
25.4614022 microseconds per iteration
I prefer timerate for this kind of micro-benchmarking:
% namespace import ::tcl::unsupported::timerate
% timerate -calibrate {}
0.03257451263357219 µs/#-overhead 0.032807 µs/# 59499506 # 30481304 #/sec
% proc foo {y} {set x 1; bar $y}
% proc bar {y} {upvar 1 x x; list $x $y}
% timerate {foo 2} 10000
0.437240 µs/# 21285016 # 2287075 #/sec 9306.651 net-ms
% proc bar {y} {set x [uplevel 1 {set x}]; list $x $y}
% timerate {foo 2} 10000
0.612693 µs/# 15497439 # 1632137 #/sec 9495.179 net-ms
(Answer holds, clearly: Use upvar).
Related
The issue:
I want to be able to sort with a custom function that depends on an outer defined variable, for example:
k = 2
sort([1,2,3], lt=(x,y) -> x + k > y)
This works all dandy and such because k is defined in the global scope.
That's where my issue lays, as I want to do something akin to:
function
k = 2
comp = (x,y) -> x + k > y
sort([1,3,3], lt=comp)
end
Which works, but feels like a hack, because my comparison function is way bigger and it feels really off to have to have it defined there in the body of the function.
For instance, this wouldn't work:
comp = (x,y) -> x + k > y # or function comp(x,y) ... end
function
k = 2
sort([1,3,3], lt=comp)
end
So I'm just wondering if there's any way to capture variables such as k like you'd be able to do with lambda functions in C++.
Is this what you want?
julia> comp(k) = (x,y) -> x + k > y
comp (generic function with 1 method)
julia> sort([1,3,2,3,2,2,2,3], lt=comp(2))
8-element Vector{Int64}:
3
2
2
2
3
2
3
1
I have a quick question :
In ruby, If I write
def test
foo && a == b && c == "bar"
end
if foo is null or false, will it keep evaluating the rest of the expression ?
Does it change anything if I do this instead
def test
a == b && c == "bar" if foo
end
thanks a lot
Theory
&& is a lazy operator, just like ||.
It means that in a && b, if a is false or nil, Ruby won't bother to check b because a && b will be false/nil anyway.
This behaviour is actually desired, because it saves time and could avoid NoMethodErrors.
if a && method_which_requires_a_non_nil_parameter(a)
# ...
end
method_which_requires_a_non_nil_parameter wouldn't be called at all if a is nil.
or :
x = x || long_method_to_calculate_x
is often used for caching, more often written as :
#x ||= long_method_to_calculate_x
Answer
def test
foo && a == b && c == "bar"
end
The rest of the expression won't be evaluated if foo is nil or false :
a, b, c could even be undefined without raising a NameError.
def test
a == b & c == "bar" if foo
end
If foo is truthy, the results will be exactly the same.
If foo is nil or false, the 2 equalities won't be evaluated, just like with the first example. But :
If foo is nil, both test will return nil.
If foo is false, first example will return false, second example will return nil.
"If foo is null or false, will it keep evaluating the rest of the expression?"
No, it will not
This table should help you in such questions:
The following table is ordered according to descending precedence (highest precedence at the top)
N A M Operator(s) Description
- - - ----------- -----------
1 R Y ! ~ + boolean NOT, bitwise complement, unary plus
(unary plus may be redefined from Ruby 1.9 with +#)
2 R Y ** exponentiation
1 R Y - unary minus (redefine with -#)
2 L Y * / % multiplication, division, modulo (remainder)
2 L Y + - addition (or concatenation), subtraction
2 L Y << >> bitwise shift-left (or append), bitwise shift-right
2 L Y & bitwise AND
2 L Y | ^ bitwise OR, bitwise XOR (exclusive OR)
2 L Y < <= >= > ordering
2 N Y == === != =~ !~ <=> equality, pattern matching, comparison
(!= and !~ may not be redefined prior to Ruby 1.9)
2 L N && boolean AND
2 L N || boolean OR
2 N N .. ... range creation (inclusive and exclusive)
and boolean flip-flops
3 R N ? : ternary if-then-else (conditional)
2 L N rescue exception-handling modifier
2 R N = assignment
2 R N **= *= /= %= += -= assignment
2 R N <<= >>= assignment
2 R N &&= &= ||= |= ^= assignment
1 N N defined? test variable definition and type
1 R N not boolean NOT (low precedence)
2 L N and or boolean AND, boolean OR (low precedence)
2 N N if unless while until conditional and loop modifiers
I'd like to write a conditional lambda in Ruby. The Python equivalent of what I'd like to write is:
even = (lambda x: x if x % 2 == 0 else 0)
My attempt to write this in Ruby looks like:
even = -> (x) {x if x % 2 == 0 else 0}
Unfortunately, that does not work. Is there any way to fix this?
You have several options here to express this. The long-form is this:
if (x % 2 == 0)
x
else
0
end
Note that a trailing if or unless cannot have a secondary condition like else. You need to use the full form.
If you want a short version, you use the ternary operator:
(x % 2 == 0) ? x : 0
What you could also do is this:
(x % 2 == 0) and x or 0
As others have observed there's a method called even? which does the modulo for you, so that can collapse this further:
x.even? ? x : 0
Ruby's ternary operator has this syntax
x % 2 == 0 ? x : 0
You don't even need a conditional.
p = ->(x) { x*(1-x%2) }
p.call(4) #=> 4
p.call(5) #=> 0
Note procs can be called in multiple ways:
p[4] #=> 4
p.(4) #=> 4
p.yield(4) #=> 4
p === 4 #=> 4
p(4) #=> 4
The last of these may be archaic.
Wrong syntax. You can write it like this:
even = -> (x) {if x % 2 == 0; x; else; 0; end}
However, for such one-liners, it is more common to use the ternary ?: operator, as other have suggested in this thread.
Your syntax is wrong:
The then-block comes after the condition, not before it.
The then-block is separated from the condition by the then keyword, a semicolon, or a newline.
The conditional expression is terminated with an end keyword.
So, any of the following is valid:
# idiomatic:
if x % 2 == 0 then x else 0 end
# idiomatic:
if x % 2 == 0
x
else
0
end
# non-idiomatic:
if x % 2 == 0; x else 0 end
# non-idiomatic:
if x % 2 == 0 then
x
else
0
end
# non-idiomatic:
if x % 2 == 0
x else 0 end
# … and many other non-idiomatic variations
Ruby also has a conditional operator:
x % 2 ? x : 0
But I personally find it ugly and unreadable. It also has different precedence than the conditional expression, which may be surprising to some. (Witness the myriad of variations of the same question about the conditional operator here on StackOverflow.) And it is completely unnecessary: in C, where if is a conditional statement, the conditional operator is required because it is an expression. In Ruby, everything is an expression anyway, there are no statements, so of course if is an expression, too.
Suppose I have two procedures p1 and p2 on the stack and I want to consume them and leave on the stack a new procedure that combines their effects. I would like a procedure to do this. This is easy enough if I am always willing to do a little dictionary bookkeeping. But can I do it without introducing any names? (Note that I want the resulting procedure, not just to execute the combined effects on the current stack.)
Consider for example
/compose {<< /f1 4 2 roll /f2 exch >>begin {f1 f2} end}bind def
This won't work of course because f1 and f2 will be unknown after end. But this broken code should illustrate what I'm after.
It's totally possible, and not terribly difficult. You make a new array with each procedure object followed by the executable name exec. Then make that array executable.
/combine { % {a} {b} . {{a} exec {b} exec}
/exec cvx exch % {a} exec {b}
/exec cvx % {a} exec {b} exec
4 array astore % [{a} exec {b} exec]
cvx % {{a} exec {b} exec}
} def
For a style closer to your original, with named arguments, I would write it like this:
% fun1 fun2 compose proc
/compose { 2 dict begin % f1 f2
{f2 f1}{exch def} forall %
({ //f1 exec //f2 exec }) % ({ //f1 exec //f2 exec })
cvx exec % { <f1> exec <f2> exec }
end } def
The //immediate-name syntax is very powerful. Here I use a code template in a string. When the string is executed cvx exec it invokes the scanner upon the contents and it is then that it automatically loads all tokens prefixed with double-slash //. The comment <f1> indicates the contents of the named variable. Just like an {executable array} in the program stream is not executed but yields the proc on the stack, execing a string containing one will also yield the proc on the stack.
For the named arguments style, I make use of a few special rules of postscript: executable arrays are not executed, thus the array of variable names can be written as an executable array and then used as data without any additional hassle. But by using the executable syntax, the contents -- the names -- can be written without the /s. So, instead of [ /f2 /f1 ] we can write the shorter { f2 f1 }.
The arguments part could also be factored into its own function.
/argsbegin { % a r g s _ {n a m e s} . -
dup length dict begin
{exch def} forall % currentdict:<</n _ /a s /m g /e r /s a>>
} def
/compose { {f2 f1} argsbegin
({//f1 exec //f2 exec}) token pop exch pop %another way to invoke the scanner
end } def
Or, to actually put the arguments the right way around, it could be like the following. It's just a little more awkward to simulate a backwards forall with a for loop.
/argsbegin { % a r g s _ {n a m e s} . -
dup length dup dict begin % a r g s _ {} n
1 sub -1 0 { % a r g s _ {} i
3 2 roll % a r g s {} i _
3 copy % a r g s {} i _ {} i _
pop % a r g s {} i _ {} i
get % a r g s {} i _ /s
exch def % a r g s {} i
pop % a r g s {}
} for % {}
pop
} def
/compose { {f1 f2} argsbegin
({//f1 exec //f2 exec}) cvx exec
end } def
Let's say I have just called a function, f, and an error occurred somewhere in the function. I just want to be able to check out the values of different variables right before the error occurred.
Suppose my gut tells me it's a small bug, so I'm too lazy to use debug(f) and too lazy to insert browser() into the part of the function where I think things are going wrong. And I'm far too lazy to start putting in print() statements.
Here's an example:
x <- 1:5
y <- x + rnorm(length(x),0,1)
f <- function(x,y) {
y <- c(y,1)
lm(y~x)
}
Calling f(x,y) we get the following error:
Error in model.frame.default(formula = y ~ x, drop.unused.levels = TRUE) :
variable lengths differ (found for 'x')
In this example, I want grab the state of the environment just before lm() is called; that way I can call x and y and see that their lengths are different. (This example may be too simple, but I hope it gets the idea across.)
As pointed out here, there's an easy way to do this, and I think this trick has the potential to change lives for the better.
First, call this:
options(error=recover)
Now when we call f(x,y) we will have an option to choose an environment to recover. Here I select option 1, which opens up a debugger and lets me play around with variables just before lm() is called.
> f(x,y)
Error in model.frame.default(formula = y ~ x, drop.unused.levels = TRUE) :
variable lengths differ (found for 'x')
Enter a frame number, or 0 to exit
1: f(x, y)
2: lm(y ~ x)
3: eval(mf, parent.frame())
4: eval(expr, envir, enclos)
5: model.frame(formula = y ~ x, drop.unused.levels = TRUE)
6: model.frame.default(formula = y ~ x, drop.unused.levels = TRUE)
Selection: 1
Called from: eval(expr, envir, enclos)
Browse[1]> x
[1] 1 2 3 4 5
Browse[1]> y
[1] 1.6591197 0.5939368 4.3371049 4.4754027 5.9862130 1.0000000
You could also just use the debug() function:
> debug(f)
> f(x,y)
debugging in: f(x, y)
debug: {
y <- c(y, 1)
lm(y ~ x)
}
Browse[1]>
debug: y <- c(y, 1)
Browse[1]> x
[1] 1 2 3 4 5
Browse[1]> y
[1] 2.146553 2.610003 2.869081 2.758753 4.433881
options(error=recover)
Probably answers the question best. However, I wanted to mention another handy debugging tool, traceback(). Calling this right after an error has occurred is often enough to pinpoint the bug.