Related
Isn't order of execution generally from left to right in Raku?
my #a = my #b = [9 , 3];
say (#a[1] - #a[0]) == (#b[1] R- #b[0]); # False {as expected}
say (#a.pop() - #a.pop()) == (#b.pop() R- #b.pop()); # True {Huh?!?}
This is what I get in Rakudo(tm) v2020.12 and 2021.07.
The first 2 lines make sense, but the third I can not fathom.
It is.
But you should realize that the minus infix operator is just a subroutine under the hood, taking 2 parameters that are evaluated left to right. So when you're saying:
$a - $b
you are in fact calling the infix:<-> sub:
infix:<->($a,$b);
The R meta-operator basically creates a wrap around the infix:<-> sub that reverses the arguments:
my &infix:<R->($a,$b) = &infix:<->.wrap: -> $a, $b { nextwith $b, $a }
So, if you do a:
$a R- $b
you are in fact doing a:
infix:<R->($a,$b)
which is then basically a:
infix:<->($b,$a)
Note that in the call to infix:<R-> in your example, $a become 3, and $b becomes 9 because the order of the arguments is processed left to right. This then calls infix:<->(3,9), producing the -6 value that you would also get without the R.
It may be a little counter-intuitive, but I consider this behaviour as correct. Although the documentation could probably use some additional explanation on this behaviour.
Let me emulate what I assumed was happening in line 3 of my code prefaced with #a is the same as #b is 9, 3 (big number then little number)
(#a.pop() - #a.pop()) == (#b.pop() R- #b.pop())
(3 - 9) == (3 R- 9)
( -6 ) == ( 6 )
False
...That was my expectation. But what raku seems to be doing is
(#a.pop() - #a.pop()) == (#b.pop() R- #b.pop())
#R meta-op swaps 1st `#b.pop()` with 2nd `#b.pop()`
(#a.pop() - #a.pop()) == (#b.pop() - #b.pop())
(3 - 9) == (3 - 9)
( -6 ) == ( -6 )
True
The R in R- swaps functions first, then calls the for values. Since they are the same function, the R in R- has no practical effect.
Side Note: In fuctional programming a 'pure' function will return the same value every time you call it with the same parameters. But pop is not 'pure'. Every call can produce different results. It needs to be used with care.
The R meta op not only reverses the operator, it will also reverse the order in which the operands will be evaluated.
sub term:<a> { say 'a'; '3' }
sub term:<b> { say 'b'; '9' }
say a ~ b;
a
b
ab
Note that a happened first.
If we use R, then b happens first instead.
say a R~ b;
b
a
ba
The problem is that in your code all of the pop calls are getting their data from the same source.
my #data = < a b a b >;
sub term:<l> { my $v = #data.shift; say "l=$v"; return $v }
sub term:<r> { my $v = #data.shift; say "r=$v"; return $v }
say l ~ r;
l=a
r=b
ab
say l R~ r;
r=a
l=b
ab
A way to get around that is to use the reduce meta operator with a list
[-](#a.pop, #a.pop) == [R-](#a.pop, #a.pop)
Or in some other way make sure the pop operations happen in the order you expect.
You could also just use the values directly from the array without using pop.
[-]( #a[0,1] ) == [R-]( #a[2,3] )
Let me emulate what happens by writing the logic one way for #a then manually reversing the operands for #b instead of using R:
my #a = my #b = [9 , 3];
sub apop { #a.pop }
sub bpop { #b.pop }
say apop - apop; # -6
say bpop - bpop; # -6 (operands *manually* reversed)
This not only appeals to my sense of intuition about what's going on, I'm thus far confused why you were confused and why Liz has said "It may be a little counter-intuitive" and you've said it is plain unintuitive!
Say that I have the following list of equations:
list: [x=1, y=2, z=3];
I use this pattern often to have multiple return values from a function. Kind of of like how you would use an object, in for example, javascript. However, in javascript, I can do things like this. Say that myFunction() returns the object {x:1, y:2, z:3}, then I can destructure it with this syntax:
let {x,y,z} = myFunction();
And now x,y,z are assigned the values 1,2,3 in the current scope.
Is there anything like this in maxima? Now I use this:
x: subst(list, x);
y: subst(list, y);
z: subst(list, z);
How about this. Let l be a list of equations of the form somesymbol = somevalue. I think all you need is:
map (lhs, l) :: map (rhs, l);
Here map(lhs, l) yields the list of symbols, and map(rhs, l) yields the list of values. The operator :: means evaluate the left-hand side and assign the right-hand side to it. When the left-hand side is a list, then Maxima assigns each value on the right-hand side to the corresponding element on the left.
E.g.:
(%i1) l : [a = 12, b = 34, d = 56] $
(%i2) map (lhs, l) :: map (rhs, l);
(%o2) [12, 34, 56]
(%i3) values;
(%o3) [l, a, b, d]
(%i4) a;
(%o4) 12
(%i5) b;
(%o5) 34
(%i6) d;
(%o6) 56
You can probably achieve it and write a function that could be called as f(['x, 'y, 'z], list); but you will have to be able to make some assignments between symbols and values. This could be done by writing a tiny ad hoc Lisp function being:
(defun $assign (symb val) (set symb val))
You can see how it works (as a first test) by first typing (form within Maxima):
:lisp (defun $assign (symb val) (set symb val))
Then, use it as: assign('x, 42) which should assign the value 42 to the Maxima variable x.
If you want to go with that idea, you should write a tiny Lisp file in your ~/.maxima directory (this is a directory where you can put your most used functions); call it for instance myfuncs.lisp and put the function above (without the :lisp prefix); then edit (in the very same directory) your maxima-init.mac file, which is read at startup and add the two following things:
add a line containing load("myfuncs.lisp"); before the following part;
define your own Maxima function (in plain Maxima syntax with no need to care about Lisp). Your function should contain some kind of loop for performing all assignments; now you could use the assign(symbol, value) function for each variable.
Your function could be something like:
f(vars, l) := for i:1 thru length(l) do assign(vars[i], l[i]) $
which merely assign each value from the second argument to the corresponding symbol in the first argument.
Thus, f(['x, 'y], [1, 2]) will perform the expected assigments; of course you can start from that for doing more precisely what you need.
Just started Haskell, it's said that everything in Haskell is "immutable" except IO package. So when I bind a name to something, it's always something immutable? Question, like below:
Prelude> let removeLower x=[c|c<-x, c `elem` ['A'..'Z']]
Prelude> removeLower "aseruiiUIUIdkf"
"UIUI"
So here:
1. “removeLower" is an immutable? Even it's a function object?
But I can still use "let" to assign something else to this name.
2. inside the function "c<-x" seems that "c" is a variable.
It is assigned by list x's values.
I'm using the word "variable" from C language, not sure how Haskell name all its names?
Thanks.
If you're familiar with C, think of the distinction between declaring a variable and assigning a value to it. For example, you can declare a variable on its own and later assign to it:
int i;
i = 7;
Or you can declare a variable and assign initial value at the same time:
int i = 7;
And in either case, you can mutate the value of a variable by assigning to it once more after the first initialization or assignment:
int i = 7; // Declaration and initial assignment
i = 5; // Mutation
Assignment in Haskell works exclusively like the second example—declaration with initialization:
You declare a variable;
Haskell doesn't allow uninitialized variables, so you are required to supply a value in the declaration;
There's no mutation, so the value given in the declaration will be the only value for that variable throughout its scope.
I bolded and hyperlinked "scope" because it's the second critical component here. This goes one of your questions:
“removeLower" is an immutable? Even it's a function object? But I can still use "let" to assign something else to this name.
After you bind removeLower to the function you define in your example, the name removeLower will always refer to that function within the scope of that definition. This is easy to demonstrate in the interpreter. First, let's define a function foo:
Prelude> let foo x = x + 2
Prelude> foo 4
6
Now we define an bar that uses foo:
Prelude> let bar x = foo (foo x)
Prelude> bar 4
8
And now we "redefine" foo to something different:
Prelude> let foo x = x + 3
Prelude> foo 4
7
Now what do you think happens to bar?
Prelude> bar 4
8
It remains the same! Because the "redefinition" of foo doesn't mutate anything—it just says that, in the new scope created by the "redefinition", the name foo stands for the function that adds three. The definition of bar was made in the earlier scope where foo x = x + 2, so that's the meaning that the name foo has in that definition of bar. The original value of foo was not destroyed or mutated by the "redefinition."
In a Haskell program as much as in a C program, the same name can still refer to different values in different scopes of the program. This is what makes "variables" variable. The difference is that in Haskell you can never mutate the value of a variable within one scope. You can shadow a definition, however—uses of a variable will refer to the "nearest" definition of that name in some sense. (In the case of the interpreter, the most recent let declaration for that variable.)
Now, with that out of the way, here are the syntaxes that exist in Haskell for variable binding ("assignment"). First, there's top-level declarations in a module:
module MyLibrary (addTwo) where
addTwo :: Int -> Int
addTwo x = x + 2
Here the name addTwo is declared with the given function as its value. A top level declaration can have private, auxiliary declarations in a where block:
addSquares :: Integer -> Integer
addSquares x y = squareOfX + squareOfY
where square z = z * z
squareOfX = square x
squareOfY = square y
Then there's the let ... in ... expression, that allows you to declare a local variable for any expression:
addSquares :: Integer -> Integer
addSquares x y =
let square z = z * z
squareOfX = square x
squareOfY = square y
in squareOfX + squareOfY
Then there's the do-notation that has its own syntax for declaring variables:
example :: IO ()
example = do
putStrLn "Enter your first name:"
firstName <- getLine
putStrLn "Enter your lasst name:"
lastName <- getLine
let fullName = firstName ++ " " ++ lastName
putStrLn ("Hello, " ++ fullName ++ "!")
The var <- action assigns a value that is produced by an action (e.g., reading a line from standard input), while let var = expr assigns a value that is produced by a function (e.g., concatenating some strings). Note that the let in a do block is not the same thing as the let ... in ... from above!
And finally, in list comprehension you get the same assignment syntax as in do-notation.
It's referring to the monadic bind operator >>=. You just don't need to explicitly write a lambda as right hand side parameter. The list comprension will be compiled down to the monadic actions defined. And by that it means exactly the same as in a monadic environment.
In fact you can replace the list comprension with a simple call to filter:
filter (`elem` ['A' .. 'Z']) x
To answer your question regarding the <- syntactic structure a bit clearer:
[c| c <- x]
is the same as
do c <- x
return c
is the same as
x >>= \c -> return c
is the same as
x >>= return
Consider the official documentation of Haskell for further reading: https://hackage.haskell.org/package/base-4.8.2.0/docs/Control-Monad.html#v:-62--62--61-
[c|c<-x, c `elem` ['A'..'Z']]
is a list comprehension, and c <- x is a generator where c is a pattern to be matched from the elements of the list x. c is a pattern which is successively bound to the elements of the input list x which are a, s, e, u, ... when you evaluate removeLower "aseruiiUIUIdkf".
c `elem` ['A'..'Z']
is a predicate which is applied to each successive binding of c inside the comprehension and an element of the input only appears in the output list if it passes this predicate.
We have this assignment for our Prolog course. After two months of one hour per week of Prolog, it is still an enigma to me, my thinking seems unable to adapt from procedural languages - yet.
There is a knowledge base containing predicates/functors with the same name and arities 1, 2 and 3.
The call form should be
search(functor_name, argument, S).
The answers should find all occurrences with this functor name and argument, regardless of arity.
The answers should be of the form:
S = functor_name(argument);
S = functor_name(argument,_);
S = functor_name(_,argument);
S = functor_name(argument,_,_);
S = functor_name(_,argument,_);
S = functor_name(_,_,argument);
false.
I have found out that I could use call to test if the entry in the knowledge base exists.
But call does not seem to work with a variable for the functor name. I am totally baffled, no idea how to use a variable for a functor name.
UPDATE:
My question has been partly answered.
My new code gives me true and false for arities 1, 2 and 3 (see below).
search(Person,Predicate) :-
ID = Person, Key = Predicate, current_functor(Key,1),
call(Key,ID)
; ID = Person, Key = Predicate, current_functor(Key,2),
(call(Key,ID,_);call(Key,_,ID))
; ID = Person, Key = Predicate, current_functor(Key,3),
(call(Key,ID,_,_);call(Key,_,ID,_);call(Key,_,_,ID)).
UPDATE2:
Another partial answer has come in. That one gives me S as a list of terms, but the "other" arguments are placeholders:
search2(Predicate, Arg, S) :-
( Arity = 2 ; Arity = 3 ; Arity = 4 ),
functor(S, Predicate, Arity),
S =.. [_,Predicate|Args],
member(Arg, Args).
The result is quite nice. Still missing: the Predicate should not be inside the brackets and the other arguments should be taken literally from the knowledge base, not written as placeholders. The current result looks like this:
?- search2(parent,lars,S).
S = parent(parent, lars) ;
S = parent(parent, lars, _G1575) ;
S = parent(parent, _G1574, lars) ;
S = parent(parent, lars, _G1575, _G1576) ;
S = parent(parent, _G1574, lars, _G1576) ;
S = parent(parent, _G1574, _G1575, lars).
I am giving up with this question, because the question was posed in the wrong way from the beginning. I should have asked more specifically - which I could not, because I am still no good in Prolog.
#false helped me most. I am accepting his answer.
There are two approaches here, one "traditional" (1970s) that implements literally what you want:
search(F, Arg, S) :-
( N = 1 ; N = 2 ; N = 3 ), % more compactly: between(1,3, N)
functor(S, F, N),
S =.. [_|Args], % more compactly: between(1,N, I), arg(I,S,Arg)
member(Arg, Args).
The other reconsiders the explicit construction of the goal. Actually, if you have a functor F, and arguments A1, A2, A3 you can immediately write the goal call(F, A1, A2, A3) without any use of functor/3 or (=..)/2.
There are many advantages of using call(F, A1, A2, A3) in place of Goal =.. [F, A1, A2, A3], call(Goal): In many situations it is cleaner, faster, and much easier to typecheck. Further, when using a module system, the handling of potential module qualifications for F will work seamlessly. Whereas (=..)/2 will have to handle all ugly details explicitly, that is more code, more errors.
search(F,A,call(F,A)).
search(F,A,call(F,A,_)).
search(F,A,call(F,_,A)).
search(F,A,call(F,A,_,_)).
search(F,A,call(F,_,A,_)).
search(F,A,call(F,_,_,A)).
If you want to shorten this, then rather construct call/N dynamically:
search(F, Arg, S) :-
( N = 2 ; N = 3 ; N = 4 ),
functor(S, call, N),
S =.. [_,F|Args],
member(Arg, Args).
Note that call needs an extra argument for the functor F!
You can use the "univ" operator, =.., to construct a goal dynamically:
?- F=member, X=1, L=[1,2,3], Goal =.. [F, X, L], call(Goal).
F = member,
X = 1,
L = [1, 2, 3],
Goal = member(1, [1, 2, 3]) .
I've read about it in a book but it wasn't explained at all. I also never saw it in a program. Is part of Prolog syntax? What's it for? Do you use it?
It represents implication. The righthand side is only executed if the lefthand side is true. Thus, if you have this code,
implication(X) :-
(X = a ->
write('Argument a received.'), nl
; X = b ->
write('Argument b received.'), nl
;
write('Received unknown argument.'), nl
).
Then it will write different things depending on it argument:
?- implication(a).
Argument a received.
true.
?- implication(b).
Argument b received.
true.
?- implication(c).
Received unknown argument.
true.
(link to documentation.)
It's a local version of the cut, see for example the section on control predicated in the SWI manual.
It is mostly used to implement if-then-else by (condition -> true-branch ; false-branch). Once the condition succeeds there is no backtracking from the true branch back into the condition or into the false branch, but backtracking out of the if-then-else is still possible:
?- member(X,[1,2,3]), (X=1 -> Y=a ; X=2 -> Y=b ; Y=c).
X = 1,
Y = a ;
X = 2,
Y = b ;
X = 3,
Y = c.
?- member(X,[1,2,3]), (X=1, !, Y=a ; X=2 -> Y=b ; Y=c).
X = 1,
Y = a.
Therefore it is called a local cut.
It is possible to avoid using it by writing something more wordy. If I rewrite Stephan's predicate:
implication(X) :-
(
X = a,
write('Argument a received.'), nl
;
X = b,
write('Argument b received.'), nl
;
X \= a,
X \= b,
write('Received unknown argument.'), nl
).
(Yeah I don't think there is any problem with using it, but my boss was paranoid about it for some reason, so we always used the above approach.)
With either version, you need to be careful that you are covering all cases you intend to cover, especially if you have many branches.
ETA: I am not sure if this is completely equivalent to Stephan's, because of backtracking if you have implication(X). But I don't have a Prolog interpreter right now to check.