Use imported Algebraic Data Type in eval - rascal

I'm using the eval function to evaluate an abstract list pattern against a list and it keeps coming up with an Undeclared Variable error. Below is included a small reproducible example.
module PuzzleScript::Test::Engine::EvalExample
import util::Eval;
import IO;
data Animal = dog() | cat();
void main(){
bool boolean = [*_, cat(), *_] := [dog(), cat()];
if (boolean) println("True 1");
println("[*_, cat(), *_] := [dog(), cat()];");
Result[bool] re = eval(#bool, "[*_, cat(), *_] := [dog(), cat()];");
if (re.val) println("True 2");
}
Which generates the following error
Rascal Version: 0.18.2, see |release-notes://0.18.2|
rascal>import PuzzleScript::Test::Engine::EvalExample;
ok
rascal>main()
True 1
[*_, cat(), *_] := [dog(), cat()];
|std:///util/Eval.rsc|(622,1030,<23,0>,<60,95>): StaticError(
"Undeclared variable: dog\nAdvice: |http://tutor.rascal-mpl.org/Errors/Static/UndeclaredVariable/UndeclaredVariable.html|",
|eval:///?command=[*_,%2520cat(),%2520*_]%20:=%20[dog(),%2520cat()];|(20,3,<1,20>,<1,23>))
at $evalinstance$0(|main://$evalinstance$0|)
at *** somewhere ***(|std:///util/Eval.rsc|(622,1030,<23,0>,<60,95>))
at eval(|project://AutomatedPuzzleScript/src/PuzzleScript/Test/Engine/EvalExample.rsc|(288,36,<13,31>,<13,67>))
at $root$(|prompt:///|(0,47,<1,0>,<1,47>)ok
rascal>
As far as I understand, the error happens when it tries to evaluate the dog constructor on the right side of the pattern. I'm looking for a solution that would allow me to make the environment available to the eval function without having to re-import everything in the eval. The reason I'm doing it this way is that I haven't found a way to dynamically generate abstract patterns, if there's a way I'd be glad to hear about it since it is the root of my current issue.

eval is not an often used function in Rascal; do you really need to dynamically create patterns?
there is the node pattern: (str name)() which in this case would match any constructor with no arguments
the real answer is that if you do import the right modules in the call to eval those modules will be cached by the interpreter which is used by the eval function
so that would not be slow
however, module reloading is not well-supported and you might have to restart the shell to get a fresh version into the eval evaluator.

Related

Nix overlays and override pattern

I have trouble understanding Nix overlays and the override pattern. What I want to do is add something to "patches" of gdb without copy/pasting
the whole derivation.
From Nix Pills I kind of see that override just mimics OOP, in reality it is just another attribute of the set. But how does it work then? Override is a function from the original attribute set to a transformed one that again has a predefined override function?
And as Nix is a functional language you also don't have variables only bindings which you can shadow in a different scope. But that still doesn't explain how overlays achieve their "magic".
Through ~/.config/nixpkgs I have configured a test overlay approximately like this:
self: super:
{
test1 = super.gdb // { name = "test1"; buildInputs = [ super.curl ]; };
test2 = super.gdb // { name = "test2"; buildInputs = [ super.coreutils ]; };
test3 = super.gdb.override { pythonSupport = false; };
};
And I get:
nix-repl> "${test1}"
"/nix/store/ib55xzrp60fmbf5dcswxy6v8hjjl0s34-gdb-8.3"
nix-repl> "${test2}"
"/nix/store/ib55xzrp60fmbf5dcswxy6v8hjjl0s34-gdb-8.3"
nix-repl> "${test3}"
"/nix/store/vqlrphs3a2jfw69v8kwk60vhdsadv3k5-gdb-8.3"
But then
$ nix-env -iA nixpkgs.test1
replacing old 'test1'
installing 'test1'
Can you explain me those results please? Am I correct that override can just alter the "defined interface" - that is all parameters of the function and as "patches" isn't a parameter of gdb I won't be able to change it? What is the best alternative then?
I will write an answer in case anyone else stumbles on this.
Edit 21.8.2019:
what I actually wanted is described in https://nixos.org/nixpkgs/manual/#sec-overrides
overrideDerivation and overrideAttrs
overrideDerivation is basically "derivation (drv.drvAttrs // (f drv))" and overrideAttrs is defined as part of mkDerivation in https://github.com/NixOS/nixpkgs/blob/master/pkgs/stdenv/generic/make-derivation.nix
And my code then looks like:
gdb = super.gdb.overrideAttrs (oldAttrs: rec {
patches = oldAttrs.patches ++ [
(super.fetchpatch {
name = "...";
url = "...";
sha256 = "...";
})
];
});
The question title is misleading and comes from my fundamental misunderstanding of derivations. Overlays work exactly as advertised. And they are probably also not that magic. Just some recursion where endresult is result of previous step // output of last overlay function.
What is the purpose of nix-instantiate? What is a store-derivation?
Correct me please wherever I am wrong.
But basically when you evaluate Nix code the "derivation function" turns a descriptive attribute set (name, system, builder) into an "actual derivation". That "actual derivation" is again an attribute set, but the trick is that it is backed by a .drv file in the store. So in some sense derivation has side-effects. The drv encodes how the building is supposed to take place and what dependencies are required. The hash of this file also determines the directory name for the artefacts (despite nothing was built yet). So implicitly the name in the nix store also depends on all build inputs.
When I was creating a new derivation sort of like Frankenstein based on tying together existing derivations all I did was create multiple references to the same .drv file. As if I was copying a pointer with the result of getting two pointers pointing to the same value on the heap. I was able to change some metadata but in the end the build procedure was still the same. Infact as Nix is pure I bet there is no way to even write to the filesystem (to change the .drv file) - except again with something that wraps the derivation function.
Override on the other hand allows you to create a "new instance". Due to "inputs pattern" every package in Nix is a function from a dependencies attribute set to the actual code that in the end invokes the "derivation function". With override you are able to call that function again which makes "derivation function" get different parameters.

Requiring a LuaJIT module in a subdir is overwriting a module of the same name in the parent dir

I have a file setup like this:
main.lua (requires 'mydir.b' and then 'b')
b.lua
mydir/
b.so (LuaJIT C module)
From main, I do this:
function print_loaded()
for k, v in pairs(package.loaded) do print(k, v) end
end
print_loaded()
require 'mydir.b'
print_loaded()
-- This would now include 'mydir.b' instead of 'b':
local b = require 'b'
The outputs of the prints show that my call to require 'mydir.b' is setting the return value as the value of package.loaded['b'] as well as the expected package.loaded['mydir.b']. I wanted to have package.loaded['b'] left unset so that I can later require 'b' and not end up with the (in my opinion incorrectly) cached value from mydir.b.
My question is: What's a good way to deal with this?
In my case, I want to be able to copy around mydir as a subdir of any of my LuaJIT projects, and not have to worry about mydir.whatever polluting the module namespace by destroying any later requires of whatever at the parent directory level.
In anticipation of people saying, "just rename your modules!" Yes. I can do that. But I'd love to know if there's a better solution that allows me to simply not have to worry about the name collisions at all.
The problem was that I was calling luaL_register incorrectly from within my b.so's source file (b.c).
Here is the bad code that caused the problem:
static const struct luaL_reg b[] = {
/* set up a list of function pointers here */
};
int luaopen_mydir_b(lua_State *L) {
luaL_register(L, "b", b); // <-- PROBLEM HERE (see below)
return 1; // 1 = # Lua-visible return values on the stack.
}
The problem with the highlighted line is that it will specifically set package.loaded['b'] to have the return value of this module when it's loaded. This can be fixed by replacing the line with this:
luaL_register(L, "mydir.b", b);
which will set package.loaded['mydir.b'] instead, and thus leave room for later use of a module with the same name (without the mydir prefix).
I didn't realize this until long after I asked this question, when I finally got around to reading the official docs for luaL_register for Lua 5.1, which is the version LuaJIT complies with.

writing a function to do type cast

I'm trying to write a function that does type casting, which seems to be a frequently occurring activity in Rascal code. But I can't seem to get it right. The following and several variations on it fail.
public &T cast(type[&T] tp, value v) throws str {
if (tp tv := v)
return tv;
else
throw "cast failed";
}
Can someone help me out?
Some more info: I frequently use pattern matching against a pattern of the form "Type Var" (i.e. against a variable declaration) in order to tell Rascal that an expression has a certain type, e.g.
map[str,value] m := myexp
This is usually in cases where I know that myexp has type map[str,value], but omitting the matching would make Rascal's type checking mechanism complain.
In order to be a bit more defensive against mistakes, I usually wrap the matching construct in an if-then-else where an exception is raised if the match fails:
if (map[str,value] m := myexp) {
// use m
} else {
throw "cast failed";
}
I would like to shorten all such similar pieces of code using a single function that does the job generically, so that I can write instead
cast(#map[str,value], myexp)
PS. Also see How to cast a value type to Map in Rascal?
It seems that the best way to write this, if you truly need to do this, is the following:
public map[str,value] cast(map[str,value] v) = v;
public default map[str,value] cast(value v) { throw "cast failed!"; }
Then you could just say
m = cast(myexp);
and it would do what you want to do -- the actual pattern matching is moved into the function signature for cast, with a case specific to the type you are wanting to use and a case that handles everything that doesn't otherwise match.
However, I'm still not sure why you are using type value, either here (inside the map) or in the linked question. The "standard" Rascal way of handling cases where you could have one of multiple choices is to define these with a user-defined data type and constructors. You could then use pattern matching to match the constructors, or use the is and has keywords to interrogate a value to check to see if it was created using a specific constructor or if it has a specific field, respectively. The rule for fields is that all occurrences of a field in the constructor definitions for a given ADT have the same type. So, it may help to know more about your usage scenario to see if this definition of cast is the best option or if there is a better solution to your problem.
EDITED
If you are reading JSON, an alternate way to do it is to use the JSON grammar and AST that also live in that part of the library (I think the one you are using is more of a stream reader, like our current text readers and writers, but I would need to look at the code more to be sure). You can then do something like this (long output included to give an idea of the results):
rascal>import lang::json::\syntax::JSON;
ok
rascal>import lang::json::ast::JSON;
ok
rascal>import lang::json::ast::Implode;
ok
ascal>js = buildAST(parse(#JSONText, |project://rascal/src/org/rascalmpl/library/lang/json/examples/twitter01.json|));
Value: object((
"since_id":integer(0),
"refresh_url":string("?since_id=202744362520678400&q=amsterdam&lang=en"),
"page":integer(1),
"since_id_str":string("0"),
"completed_in":float(0.058),
"results_per_page":integer(25),
"next_page":string("?page=2&max_id=202744362520678400&q=amsterdam&lang=en&rpp=25"),
"max_id_str":string("202744362520678400"),
"query":string("amsterdam"),
"max_id":integer(202744362520678400),
"results":array([
object((
"from_user":string("adekamel"),
"profile_image_url_https":string("https:\\/\\/si0.twimg.com\\/profile_images\\/2206104506\\/339515338_normal.jpg"),
"in_reply_to_status_id_str":string("202730522013728768"),
"to_user_id":integer(215350297),
"from_user_id_str":string("366868475"),
"geo":null(),
"in_reply_to_status_id":integer(202730522013728768),
"profile_image_url":string("http:\\/\\/a0.twimg.com\\/profile_images\\/2206104506\\/339515338_normal.jpg"),
"to_user_id_str":string("215350297"),
"from_user_name":string("nurul amalya \\u1d54\\u1d25\\u1d54"),
"created_at":string("Wed, 16 May 2012 12:56:37 +0000"),
"id_str":string("202744362520678400"),
"text":string("#Donnalita122 #NaishahS #fatihahmS #oishiihotchoc #yummy_DDG #zaimar93 #syedames I\'m here at Amsterdam :O"),
"to_user":string("Donnalita122"),
"metadata":object(("result_type":string("recent"))),
"iso_language_code":string("en"),
"from_user_id":integer(366868475),
"source":string("<a href="http:\\/\\/blackberry.com\\/twitter" rel="nofollow">Twitter for BlackBerry\\u00ae<\\/a>"),
"id":integer(202744362520678400),
"to_user_name":string("Rahmadini Hairuddin")
)),
object((
"from_user":string("kelashby"),
"profile_image_url_https":string("https:\\/\\/si0.twimg.com\\/profile_images\\/1861086809\\/me_beach_normal.JPG"),
"to_user_id":integer(0),
"from_user_id_str":string("291446599"),
"geo":null(),
"profile_image_url":string("http:\\/\\/a0.twimg.com\\/profile_images\\/1861086809\\/me_beach_normal.JPG"),
"to_user_id_str":string("0"),
"from_user_name":string("Kelly Ashby"),
"created_at":string("Wed, 16 May 2012 12:56:25 +0000"),
"id_str":string("202744310872018945"),
"text":string("45 days til freedom! Cannot wait! After Paris: London, maybe Amsterdam, then southern France, then CANADA!!!!"),
"to_user":null(),
"metadata":object(("result_type":string("recent"))),
"iso_language_code":string("en"),
"from_user_id":integer(291446599),
"source":string("<a href="http:\\/\\/mobile.twitter.com" rel="nofollow">Mobile Web<\\/a>"),
"id":integer(202744310872018945),
"to_user_name":null()
)),
object((
"from_user":string("johantolsma"),
"profile_image_url_https":string("https:\\/\\/si0.twimg.com\\/profile_images\\/1961917557\\/image_normal.jpg"),
"to_user_id":integer(0),
"from_user_id_str":string("23632499"),
"geo":null(),
"profile_image_url":string("http:\\/\\/a0.twimg.com\\/profile_images\\/1961917557\\/image_normal.jpg"),
"to_user_id_str":string("0"),
"from_user_name":string("Johan Tolsma"),
"created_at":string("Wed, 16 May 2012 12:56:16 +0000"),
"id_str":string("202744274050236416"),
"text":string("RT #agerolemou: Office space for freelancers in Amsterdam http:\\/\\/t.co\\/6VfHuLeK"),
"to_user":null(),
"metadata":object(("result_type":string("recent"))),
"iso_language_code":string("en"),
"from_user_id":integer(23632499),
"source":string("<a href="http:\\/\\/itunes.apple.com\\/us\\/app\\/twitter\\/id409789998?mt=12" rel="nofollow">Twitter for Mac<\\/a>"),
"id":integer(202744274050236416),
"to_user_name":null()
)),
object((
"from_user":string("hellosophieg"),
"profile_image_url_https":string("https:\\/\\/si0.twimg.com\\/profile_images\\/2213055219\\/image_normal.jpg"),
"to_user_id":integer(0),
"from_user_id_str":string("41153106"),
"geo":null(),
"profile_image_url":string("http:\\/\\/a0.twimg.com\\/profile_images\\/2213055219\\/image_normal.jp...
rascal>js is object;
bool: true
rascal>js.members<0>;
set[str]: {"since_id","refresh_url","page","since_id_str","completed_in","results_per_page","next_page","max_id_str","query","max_id","results"}
rascal>js.members["results_per_page"];
Value: integer(25)
You can then use pattern matching, over the types defined in lang::json::ast::json, to extract the information you need.
The code has a bug. This is the fixed code:
public &T cast(type[&T] tp, value v) throws str {
if (&T tv := v)
return tv;
else
throw "cast failed";
}
Note that we do not wish to include this in the standard library. Rather lets collect cases where we need it and find out how to fix it in another way.
If you find you need this casting often, then you might be avoiding the better parts of Rascal, such as pattern based dispatch. See also the answer by Mark Hills.

erlang: function called with real 'fun' should be transformed with parse_transform?

I'm looking at the O'Reilly Erlang Programming book and there's an example that is run in the erlang shell that looks like this:
17> MS = ets:fun2ms(fun({Name,Country,Job}) when Job /= cook ->
[Country,Name] end).
[ ....an erlang match expression is returned.... ]
18> ets:select(countries, MS).
[[ireland,sean],[ireland,chris]]
However, when I do something similar in my code (not in the shell):
Fun = fun({Type,_,_,ObjectId,PlayerId}) when Type==player_atom, PlayerId==2 -> ObjectId end,
MatchFun = ets:fun2ms(Fun),
PlayerObjectId = ets:select(?roster_table, MatchFun),
I get FUBAR:
exit:{badarg,{ets,fun2ms,[function,called,with,real,'fun',should,be,transformed,with,parse_transform,'or',called,with,a,'fun',generated,in,the,shell]}}
(As an aside, I wonder why the error isn't 'function called with....' Probably so io:format("~p", TheErrorMessage) will line wrap?)
Anyway, I have abandoned select in favor of ets:foldl, since the latter works and - through exceptions in the fun - allows me to terminate the traversal when the first item is found. But, I'm still curious...
...wha? (I did some reading on parse_transform, and I'm new enough to erlang that I'm missing the connection.)
The badarg exception is symptom of a built-in function (or a pseudo function, as in this case) called with a wrong parameter. In this case, the ets:fun2ms/1 function.
Reading from the official documentation:
fun2ms(LiteralFun) -> MatchSpec
Pseudo function that by means of a parse_transform translates
LiteralFun typed as parameter in the function call to a match_spec.
With "literal" is meant that the fun needs to textually be written as
the parameter of the function, it cannot be held in a variable which
in turn is passed to the function).

F# top level do binding

I have a file with a module with some routines that take parameters and return unit, these routines have side-effects. I noticed that when accessing these f# routines from c# they're actually properties of type unit and when I try to access 1 property, it runs all properties in the module.
From the F# documentation all top level do bindings are run on type initialization.
What is the preferred way to write functions that should not be run on type initialization but are also not associated with other state i.e. a class with functions and member variables?
Should I put these functions inside a type and just have no records in the type?
Code example:
namespace test_space
open System.Diagnostics;
module test =
let test_1 =
Debug.WriteLine ("One")
let test_2 =
Debug.WriteLine ("Two")
I'm running this code with C#:
static void Main (string [] args)
{
Object o;
o = test.test_2;
}
And the output is:
One
Two
The problem is you didn't create functions but value bindings. test_1 is a value. test_1() is a function of type unit -> unit. Make sure you put () after the function name.
I don't fully understand the scenario you're describing - F# functions declared in a module will generally appear as methods and values will appear as properties. The code that is executed when you first access module (type initialization) is the initialization of values.
If you write just:
module Foo =
let Operation () =
printfn "hello"
...then calling Operation will be a method and calling Foo.Operation() will run the side-effect. If you can post some code that behaves unexpectedly, then someone can explain it.
Anyway, if you want to be sure about the behavior, you can write operations as static members of a class:
type Foo =
static member Operation() =
printfn "hello"
Then you can be sure that F# will compile them as static members of a class in a predictable way.

Resources