how to curry a method? - ruby

consider this code
def f x, y
x + y
end
g = lambda(&method(:f)).curry.(1)
g.(2) # => 3
the expression for g is too hard to read. Can it be simplified?

If you are using Ruby 2.2.0 or later, you can use Method#curry:
def f(x, y)
x + y
end
g = method(:f).curry[1]
p g[2] # => 3

I think the shortest (and most readable!) you can get is
g = method(:f).to_proc.curry[1]
g[2] # => 3

Related

is '#client command' or '#client event' with if statements more efficient (discord.py)

Just a quick question which I cannot find the answer too.
which piece of code is more efficient/faster
this:
#client.event
async def message(message):
if message.content == 'x':
await message.channel.send('y')
or this:
#client.command()
async def x(ctx):
await ctx.send('y')
syntax might be a little off for the client.command() part, I have only used client.event method so far.
Before answering, it's important to understand, on_message is the base of commands extension.
What it does is
commands = {} # example dictionary
#bot.command() # this registers the function in the command dictionary
async def test(ctx: commands.Context):
# some code here
# after this line is executed, your commands dictionary would look somethig like
# commands = {'test': test} (here, test is coroutine function you made)
on_message looks for a message.content, if it starts with the prefix, it gets the message without the prefix, then checks if the command called is in the dictionary, if yes, then call the command on that part with the arguments provided. If not, raise commands.CommandsNotFound
The above on_message I spoke about is the default on_message event bound to the bot. This is also a reason why commands extension doesn't work if one overrides the on_message event
Now with that out of the way, python dictionaries are implemented as hash tables. If the amount of if else staement is less then yes, they might be equally performative but in the longer run, dictionary lookup will prevail. Thus, I would say the commands extesnion is better to use.
In addition to the long run benefit, commands extension offers a much better way to manage your code.
if x == "test":
s = 1
y = 1
j = 1
print(s, y, z)
elif x == "test2":
s = 2
y = 2
j = 2
print(s, y, z)
elif x == "test3":
s = 3
y = 3
j = 3
print(s, y, z)
elif x == "test4":
s = 4
y = 4
j = 4
print(s, y, z)
elif x == "test5":
s = 5
y = 5
j = 5
print(s, y, z)
is certainly not appealing comapred to
def test1():
s = 1
y = 1
j = 1
print(s, y, z)
def test2():
s = 2
y = 2
j = 2
print(s, y, z)
def test3():
s = 3
y = 3
j = 3
print(s, y, z)
def test4():
s = 4
y = 4
j = 4
print(s, y, z)
def test5():
s = 5
y = 5
j = 5
print(s, y, z)
And it's also much easier to navigate and maintain your code with the command extension!
So, there is no reason for anyone to use if else in on_message to create commands when given a superior choice, i.e commands extesnion

Python vs Ruby: Is y greater than x and less than z?

Is there a less verbose way to compare three integer values in Ruby?
For example, in Python the following return True:
x = 2
y = 3
z = 4
x < y < z
With the same variable bindings in Ruby the following will both return true:
x < y && y < z
x.send(:<, y) && y.send(:<, z)
but this:
x < y < z
returns NoMethodError:
NoMethodError: undefined method `<' for true:TrueClass
I presume this is because the first comparison of x < y evaluates to true and the error is raised from the resulting TrueClass.instance < z? Is there a way in Ruby to compare three integer values without the use of &&?
Thank you.
You can write
(x+1...z).cover? y
or (my preference)
(x+1..z-1).cover? y
Because x, y and z are numeric, this is the same as
(x+1..z-1).include? y
See Range#cover? and Range#include?.

Invariant induction over horn-clauses with Z3py

I am currently using Z3py to to deduce some invariants which are encoded as a conjunction of horn-clauses whilst also providing a template for the invariant. I'm starting with a simple example first if you see the code snippet below.
x = 0;
while(x < 5){
x += 1
}
assert(x == 5)
This translates into the horn clauses
x = 0 => Inv(x)
x < 5 /\ Inv(x) => Inv(x +1)
Not( x < 5) /\ Inv(x) => x = 5
The invariant here is x <= 5.
I have provided a template for the invariant of the form a*x + b <= c
so that all the solver has to do is guess a set of values for a,b and c that can reduce to x <= 5.
However when I encode it up I keep getting unsat. If try to assert Not (x==5) I get a=2 , b = 1/8 and c = 2 which makes little sense to me as a counterexample.
I provide my code below and would be grateful for any help on correcting my encoding.
x = Real('x')
x_2 = Real('x_2')
a = Real('a')
b = Real('b')
c = Real('c')
s = Solver()
s.add(ForAll([x],And(
Implies(x == 0 , a*x + b <= c),
Implies(And(x_2 == x + 1, x < 5, a*x + b <= c), a*x_2 + b <= c),
Implies(And(a*x + b <= c, Not(x < 5)), x==5)
)))
if (s.check() == sat):
print(s.model())
Edit: it gets stranger for me. If I remove the x_2 definition and just replace x_2 with (x + 1) in the second horn clause as well as delete the x_2 = x_2 + 1, I get unsat whether I write Not( x==5) or x==5 in the final horn clause.
There were two things preventing your original encoding from working:
1) It's not possible to satisfy x_2 == x + 1 for all x for a single value of x_2. Thus, if you're going to write x_2 == x + 1, both x and x_2 need to be universally quantified.
2) Somewhat surprisingly, this problem is satisfiable in the integers but not in the reals. You can see the problem with the clause x < 5 /\ Inv(x) => Inv(x + 1). If x is an integer, then this is satisfied by x <= 5. However, if x is allowed to be any real value, then you could have x == 4.5, which satisfies both x < 5 and x <= 5, but not x + 1 <= 5, so Inv(x) = (x <= 5) does not satisfy this problem in the reals.
Also, you might find it helpful to define Inv(x), it cleans up the code quite a bit. Here is the encoding of your problem with those changes:
from z3 import *
# Changing these from 'Int' to 'Real' changes the problem from sat to unsat.
x = Int('x')
x_2 = Int('x_2')
a = Int('a')
b = Int('b')
c = Int('c')
def Inv(x):
return a*x + b <= c
s = Solver()
# I think this is the simplest encoding for your problem.
clause1 = Implies(x == 0 , Inv(x))
clause2 = Implies(And(x < 5, Inv(x)), Inv(x + 1))
clause3 = Implies(And(Inv(x), Not(x < 5)), x == 5)
s.add(ForAll([x], And(clause1, clause2, clause3)))
# Alternatively, if clause2 is specified with x_2, then x_2 needs to be
# universally quantified. Note the ForAll([x, x_2]...
#clause2 = Implies(And(x_2 == x + 1, x < 5, Inv(x)), Inv(x_2))
#s.add(ForAll([x, x_2], And(clause1, clause2, clause3)))
# Print result all the time, to avoid confusing unknown with unsat.
result = s.check()
print result
if (result == sat):
print(s.model())
One more thing: it's a bit strange to me to write a*x + b <= c as a template, because this is the same as a*x <= d for some integer d.

Is there a way I make a defined variable reset every time I use it?

This is the code
x = 10
y = 11
def z(q,x,y)
q = q - (x + y)
end
q = 30
z(q,x,y)
puts "#{q}"
q = 40
z(q,x,y)
puts "#{q}"
Is there a way that z(q,x,y) would reset every time I use it?
Try this:
x = 10
y = 11
def z(q,x,y)
q = q - (x + y)
end
q = 30
z1 = z(q,x,y)
puts "#{z1}"
q = 40
z2 = z(q,x,y)
puts "#{z2}"
prints (using puts):
9
19
Generally, you shouldn't modify params. In function z, q is a parameter that's been set but I think you are also wanting it to be an outside variable and mutate its state.
Here's what you want to do but please do not do this.
x = 10
y = 11
def z(q,x,y)
$q = q - (x + y)
end
$q = 30
z($q,x,y)
puts "#{$q}"
$q = 40
z($q,x,y)
puts "#{$q}"
# Prints:
# 9
# 19
This is probably bad code. Why? Globals are bad. Mutating state like this when we are blessed to have a mathematical function so pure like this is a war crime and might cause rioting. We have a math function that doesn't need to change state. We don't really want z to be responsible for:
computing a new value
setting a local variable for use later
The second part is the damning part. Z knows about its outside world when it doesn't need to.
Look at this which is similar to the other answer already here:
x = 10
y = 11
def z(q, x, y)
q - (x + y)
end
q = z(30, x, y)
puts q
q = z(40, x, y)
puts q
If you are starting out with Ruby or programming in general, read a lot of code and watch screencasts of people working live. It's the fastest route to leveling up a little bit. It's ok if it doesn't happen right away, the next time you try will be easier (years later maybe).

Ruby - newlines and operators

Consider the following code:
x = 4
y = 5
z = (y + x)
puts z
As you'd expect, the output is 9. If you introduce a newline:
x = 4
y = 5
z = y
+ x
puts z
Then it outputs 5. This makes sense, because it's interpreted as two separate statements (z = y and +x).
However, I don't understand how it works when you have a newline within parentheses:
x = 4
y = 5
z = (y
+ x)
puts z
The output is 4. Why?
(Disclaimer: I'm not a Ruby programmer at all. This is just a wild guess.)
With parens, you get z being assigned the value of
y
+x
Which evaluates to the value of the last statement executed.
End the line with \ in order to continue the expression on the next line. This gives the proper output:
x = 4
y = 5
z = (y \
+ x)
puts z
outputs 9
I don't know why the result is unexpected without escaping the newline. I just learned never to do that.
Well you won't need the escaping character \ if your lines finishes with the operator
a = 4
b = 5
z = a +
b
puts z
# => 9

Resources