If the following nix expression
let
f = "f";
o = "o";
b = "b";
func = {a ? f, b ? "a" , c ? ""}: a+b+c; #only modify this line!
in
rec {
foo = func {b="o"; c=o;}; #must evaluate to "foo"
bar = func {a=b; c="r";}; #must evaluate to "bar"
foobar = func {a=foo;b=bar;}; #must evaluate to "foobar"
}
Here {a ? f, b ? "a" , c ? ""}: a+b+c; we are declaring that a
function takes attribute set {a ? f, b ? "a" , c ? ""} as
argument.
Here func {b="o"; c=o;} we are passing an attribute set({b="o"; c=o;})to the
function.
In the first expression we have "," separating the keys of attribute set and in the second "," is separating the keys. To represent attribute set we use two different methods. Is this understanding correct.?
The syntax { param ? default }: x defines an anonymous function that takes an attribute set with optional attribute param.
in the second "," is separating the keys.
In an attribute set, you use ; as a separator. I think this is a typo because your example is correct.
You can read more about "set patterns" in function definitions in the Nix manual.
Your understanding seems to be correct.
Related
Trying to understand callPackage, so looked up its implementation where it uses lib.functionArgs (source), but there is already a builtins.functionArgs primop, an alias of __functionArgs (implemented in C).
lib.functionArgs is defined as
/* Extract the expected function arguments from a function.
This works both with nix-native { a, b ? foo, ... }: style
functions and functions with args set with 'setFunctionArgs'. It
has the same return type and semantics as builtins.functionArgs.
setFunctionArgs : (a → b) → Map String Bool.
*/
functionArgs = f: f.__functionArgs or (builtins.functionArgs f);
and the __functionArgs attribute above is coming from setFunctionArgs (source):
/* Add metadata about expected function arguments to a function.
The metadata should match the format given by
builtins.functionArgs, i.e. a set from expected argument to a bool
representing whether that argument has a default or not.
setFunctionArgs : (a → b) → Map String Bool → (a → b)
This function is necessary because you can't dynamically create a
function of the { a, b ? foo, ... }: format, but some facilities
like callPackage expect to be able to query expected arguments.
*/
setFunctionArgs = f: args:
{
__functor = self: f;
__functionArgs = args;
};
I understand what setFunctionArgs does, and the comment above its declaration tells why it is necessary, but I can't understand it; both clauses of that sentence are clear but not sure how the first statement prevents the second one to be achieved (without setFunctionArgs, that is).
danbst also tried to elucidate this further,
lib.nix adds __functionArgs attr to mimic __functionArgs builtin. It
used to "pass" actual __functionArgs result down to consumers, because
builtin __functionArgs only works on top-most function args
but not sure what the "consumers" are, and couldn't unpack the last clause (i.e., "builtin __functionArgs only works on top-most function args"). Is this a reference to the fact that Nix functions are curried, and
nix-repl> g = a: { b, c }: "lofa"
nix-repl> builtins.functionArgs g
{ }
?
lib.functionArgs also doesn't solve this problem, but I'm probably off the tracks at this point.
Notes to self
__functor is documented in the Nix manual under Sets.
$ nix repl '<nixpkgs>'
Welcome to Nix version 2.3.6. Type :? for help.
Loading '<nixpkgs>'...
Added 11530 variables.
nix-repl> f = { a ? 7, b }: a + b
nix-repl> set_f = lib.setFunctionArgs f { b = 9; }
nix-repl> set_f
{ __functionArgs = { ... }; __functor = «lambda # /nix/store/16blhmppp9k6apz41gjlgr0arp88awyb-nixos-20.03.3258.86fa45b0ff1/nixos/lib/trivial.nix:318:19»; }
nix-repl> set_f.__functionArgs
{ b = 9; }
nix-repl> set_f set_f.__functionArgs
16
nix-repl> set_f { a = 27; b = 9; }
36
lib.functionArgs wraps builtins.functionArgs in order to provide reflective access to generic functions.
This supports reflection with builtins.functionArgs:
f = { a, b, c }: #...
Now consider the eta abstraction of the same function:
f' = attrs: f attrs
This does not support reflection with builtins.functionArgs. With setFunctionArgs, you can restore that information, as long as you also use lib.functionArgs.
I recommend to avoid reflection because everything that I've seen implemented with it can be implemented without it. It expands the definition of a function to include what should normally be considered implementation details.
Anyway, the primary motivation seems to be callPackage, which can be implemented with normal attrset operations if you change all packages to add ... as in { lib, stdenv, ... }:. I do have a morbid interest in this misfeature that is function reflection, so if anyone finds another use case, please comment.
I want to use a variable that references an arithmetic operator within an if statement expression as shown below:
str = { '>60', '>60', '>-60', '=0' }
del = 75
function decode_prog(var1, var2)
op = string.sub(var1, 1, 1)
vb = tonumber(string.sub(var1, 2, 3))
if var2 op vb then
print("condition met")
else
print('condition not meet')
end
end
for i = 1, #str do
decode_prog(str[i], del)
end
When the above code executes, it should either print "condition met" or "condition not met" based on the result of the operation, however I am instead receiving an error.
You cannot substitute a native Lua operator with a variable that references a function, the only way to go about what you are attempted to do is to create a set of functions within an associative array and set the index as a reference to the respective operation you want to conduct.
Looking at your list, you have a greater than (>) and equal to (=). We create a table for these operations that takes two parameters as follows.
local operators = {
[">"] = function(x, y) return x > y end,
["="] = function(x, y) return x == y end,
-- Add more operations as required.
}
You can then invoke the respective function from the decode_prog function by obtaining the operation character from the string, along with the numeric value itself - this is possible because you can obtain the function from the associative array where the index is the string of the operation we want to conduct.
local result = operators[op](var2, number)
This calls upon the operators array, uses the op to determine which index we need to go to for our appropriate operation, and returns the value.
Final Code:
str = { '>60', '>60', '>-60', '=0' }
del = 75
local operators = {
[">"] = function(x, y) return x > y end,
["="] = function(x, y) return x == y end,
}
function decode_prog(var1, var2)
local op = string.sub(var1, 1, 1) -- Fetch the arithmetic operator we intend to use.
local number = tonumber(string.sub(var1, 2)) -- Strip the operator from the number string and convert the result to a numeric value.
local result = operators[op](var2, number) -- Invoke the respective function from the operators table based on what character we see at position one.
if result then
print("condition met")
else
print('condition not meet')
end
end
for i = 1, #str do
decode_prog(str[i], del)
end
I can't make much sense of your code or what you want to achieve doing that but if could simply use load.
You build your expression as a string and run it. Of course you should take care of two character operators like >= which I did not and you should validate your input.
local str={'>60','>60','>-60','=0'}
local del=75
function decode_prog(var1, var2)
local operator = var1:sub(1,1):gsub("=", "==")
local expr = string.format("return %d %s %s", var2,operator, var1:sub(2))
print(string.format("condition %smet", load(expr)() and "" or "not "))
end
for i,v in ipairs(str) do
decode_prog(v, del)
end
A very simple way would be to add a condition for each supported operator:
function decode_prog(var1, var2)
op = string.sub(var1, 1, 1)
vb = tonumber(string.sub(var1, 2)) --remove the last argument and use tonumber()
if vb == nil then return end --if the string does not contain number
if (op == ">" and var2 > vb) or (op == "=" and var2 == vb) --[[add more conditions here]] then
print("condition met")
else
print("condition not met")
end
end
I changed the vb=string.sub(var1,2,3) line too.
This form vb = tonumber(string.sub(var1, 2)) will allow use of numbers that have any number of digits and added tonumber() which will allow us to catch not-a-number errors when comparison would probably fail.
Then I added a logic to determine what the operator is and if the condition is met.
Operator limitations:
This will only work with operators that are one character and operator such as >= will not be possible unless you use a different character for it. ≥ will not play nicely, since it is multiple characters.
I am trying to add multiple annotations to a Java M3 node. As a working example this is what I'm trying to do:
n = \number("5");
n = setAnnotations(n, ("modifiers" : [\static()]));
n = setAnnotations(n, ("modifiers" : getAnnotations(n ["modifiers"]+\public()));
Which causes the following error:
|rascal://Driver|(1556,7,<59,57>,<59,64>): insert into collection not supported on value and Modifier
?[Advice](http://tutor.rascal-mpl.org/Errors/Static/UnsupportedOperation/UnsupportedOperation.html)
In addition I have tried:
n = \number("5");
n = setAnnotations(n, ("modifiers" : [\static()]));
n = setAnnotations(n, ("modifiers" : getAnnotations(n)["modifiers"]+[\public()]));
Which doesn't crash but produces an annotation as follows:
number("5")[
#modifiers=[
[static()],
public()
]
]
Which is not what I'm looking for. I have also tried:
n = \number("5");
n = setAnnotations(n, ("modifiers" : [\static()]));
a = [\static(), [ m | m <- getAnnotations(n)["modifiers"] ] ];
n = setAnnotations(n, (modifiers : a));
With the following error:
|rascal://Driver|(1548,11,<59,49>,<59,60>): value is not enumerable
?[Advice](http://tutor.rascal-mpl.org/Errors/Static/NotEnumerable/NotEnumerable.html)
Really I just want some way to append Modifiers to the modifiers annotation. What am I doing wrong here? Thanks.
If you just want to add an annotation to a value, valid alternatives are the following:
// as assignment statements which modify the variable `n`:
n#modifiers = [\static(), \public()]; // setting a new value for the modifiers annotation
n#modifiers += [\public()]; // short-hand to concatenate to the existing value of modifiers
n#modifiers?[] += [\public()]; // in case sometimes there is no initial value to begin with we initialize with empty list.
// as expression to create a new value assigned to m with a different annotation than n had:
m = n[#modifiers=[\static(), \public()];
m = n[#modifiers=n#modifiers + [\public()]]; // using the previous value too
Some clarification about the errors you've seen:
getAnnotations returns a value of type map[str,value], since value is the top type Rascal does not know many operations to apply to it. This explains why you can't concatenate or enumerate. It requires pattern matching to downcast to a more useful type, as in for (list[Modifier] modifiers := getAnnotations(n)["modifiers"], Modifier m <- modifiers) { ... }
to retrieve an annotation in a typed manner simply use n#modifiers which is of type list[Modifier] due to the declaration anno list[Modifier] Declaration#modifiers; somewhere in the M3 library.
I have a grammar rule like this:
a returns [string expr] : (b | c) {$expr = "Build expression from b OR c here";}
b returns [string expr] : 'B' {$expr = "From b";}
c returns [string expr] : 'C' {$expr = "From c";}
I would like to replace
$expr = "Build expression from b OR c here";
with an instruction that puts in the $expr variable whatever was returned from b OR c. I know there is a solution to this by performing this assignment like this:
a returns [string expr] : b {$expr = $b.expr;} | c {$expr = $c.expr;}
but was wondering whether there is a much simpler way like naming the whole group with a variable and using that instead:
a returns [string expr] : group = (b | c) {$expr = $group.expr;}
I've tried this and it doesn't work in ANTLR, even though the group variable is used to get the value returned by "b".
You cannot use the same label for multiple non-terminals unless they reference the same rule in the grammar. This means syntax like group=(A | B) only works for token references (A and B are terminals). The following syntax can be used for this.
a returns [string expr]
: b {$expr = $b.expr;}
| c {$expr = $c.expr;}
;
I want to implement a F# function which may accept 1 or 2 arguments. I would like to use the function like this:
let foo = ...
foo "a"
foo "a" "b"
Both the arguments can be the same type. I read the pages about match pattern, active pattern, but cannot find one works for me.
I believe this is due to some of the underlying .Net features, but I think you have to use a class with overloaded methods - something like
type t() =
static member foo a = "one arg"
static member foo (a,b) = "two args"
On a type member, you can use optional params:
type Helper private () =
static member foo (input1, ?input2) =
let input2 = defaultArg input2 "b"
input1, input2
To call this method:
Helper.foo("a")
Helper.foo("a", "b")
Is this what you're after?
You can't use optional params on a function though, unfortunately.
In addition to the other answers, here are a few more "almost solutions". They are not strictly what you wanted, but are worth knowing anyway.
Using a list (or an array) and pattern matching:
let f = function
| [a, b] -> ...
| [a] -> ...
| [] -> failwith "too few arguments"
| _ -> failwith "too many arguments"
f ["a"]
f ["a" ; "b"]
Problems: parameters are not named, not clear from function signature how many parameters it takes.
Using a record to pass all optional parameters:
type FParams = { a : string; b : string }
let fdefault = { a = "a" ; b = "b" }
let f (pars: FParams) = ...
f { fdefault with b = "c" }
Problem: a is also optional, which is not what you wanted. Can be useful though.
In addition to the other answers, you might also be able to do what you want via partial application and currying. Like this:
let foo a b =
a + b
let foo2 a =
foo 1 a;;
Obviously you'd want to fix the first parameter in the call to foo within foo2 to whatever default you want.