Is it possible to have some kind of constexpr equivalent in Erlang?
I have some expression
obj() -> func("some string")
in which func is a pure function (result does not depend on anything other than the arguments) and I would like it to be executed during compilation time. How can I achieve it?
EDIT I can accept any reasonable hacks, as long as they allow func to be a casual function
You could use ct_expand, part of Ulf Wiger's parse_trans repository. To use it, specify that the compiler should use ct_expand as a parse transform:
-compile({parse_transform, ct_expand}).
and then, for each expression you want to evaluate at compile time, wrap it in ct_expand:term/1:
obj() -> ct_expand:term(func("some string")).
See also the example module.
Erlang has things called macros, which are expanded at compilation time. Here's an example of what you can do:
a.erl:
-module(a).
-compile(export_all).
-define(FUNC(Str), "hello "++Str).
go() ->
?FUNC("world").
In the shell:
4> compile:file("a.erl", ['P']).
{ok,[]}
^C^C
At the command line:
~/erlang_programs$ cat a.p
-file("a.erl", 1).
-module(a).
-compile(export_all).
go() ->
"hello " ++ "world".
Related
In the following code:
match fnA(size) {
Some(arr) => SomeBlock::new(size, &arr, false).as_ptr().add(1) as *mut c_void,
None => ptr::null::<c_void>() as *mut c_void,
}
I want to use rust-gdb to step into SomeBlock::new(size, &arr, false). When I run it normally, I am able to step into fnA, but if I try to step when I'm on the line with Some(arr), gdb just ends up running the rest of the program and exiting.
I know I can directly insert a breakpoint at SomeBlock::new, but I was curious if there was a cleaner way of doing it.
According to the GDB documentation on Rust:
The Rust expression evaluator does not support “statement-like” expressions such as if or match, or lambda expressions.
It seems that you cannot step into anything that is inside a match expression. Note that you can step into fnA as it is evaluated before its output gets matched inside the match block.
I've seen a few other questions and answers stating that let _ = foo() destroys the result at the end of the statement rather than at scope exit, which is what let _a = foo() does.
I am unable to find any official description of this, nor any rationale for this syntax.
I'm interested in a few inter-twined things:
Is there even a mention of it in the official documentation?
What is the history behind this choice? Is it simply natural fall-out from Rust's binding / destructuring rules? Is it something inherited from another language? Or does it have some other origin?
Is there some use-case this syntax addresses that could not have been achieved using explicit scoping?
Is it simply natural fall-out from Rust's binding / destructuring rules?
Yes. You use _ to indicate that you don't care about a value in a pattern and that it should not be bound in the first place. If a value is never bound to a variable, there's nothing to hold on to the value, so it must be dropped.
All the Places Patterns Can Be Used:
match Arms
Conditional if let Expressions
while let Conditional Loops
for Loops
let Statements
Function Parameters
Is there even a mention of it in the official documentation?
Ignoring an Entire Value with _
Of note is that _ isn't a valid identifier, thus you can't use it as a name:
fn main() {
let _ = 42;
println!("{}", _);
}
error: expected expression, found reserved identifier `_`
--> src/main.rs:3:20
|
3 | println!("{}", _);
| ^ expected expression
achieved using explicit scoping
I suppose you could have gone this route and made expressions doing this just "hang around" until the scope was over, but I don't see any value to it:
let _ = vec![5];
vec![5]; // Equivalent
// Gotta wait for the scope to end to clean these up, or call `drop` explicitly
The only reason that you'd use let _ = foo() is when the function requires that you use its result, and you know that you don't need it. Otherwise, this:
let _ = foo();
is exactly the same as this:
foo();
For example, suppose foo has a signature like this:
fn foo() -> Result<String, ()>;
You will get a warning if you don't use the result, because Result has the #[must_use] attribute. Destructuring and ignoring the result immediately is a concise way of avoiding this warning in cases where you know it's ok, without introducing a new variable that lasts for the full scope.
If you didn't pattern match against the result then the value would be dropped as soon as the foo function returns. It seems reasonable that Rust would behave the same regardless of whether you explicitly said you don't want it or just didn't use it.
I am trying to write a code that calculate the size of a list.
Here is what I've done:
let rec l = function
| [] -> 0
| t::q -> 1 + l q
print_int(l ([1;2;3;4]))
The problem is that it's saying me :
It is applied to too many arguments; maybe you forgot a `;'.
When I put the double semicolon ;; at the end of the definition of l it works well, yet I've read that ;; is not useful at all if you are not coding in the REPL, so here I don't see why it's giving me this error.
The following
print_int(l [1;2;3;4])
is a toplevel expression. Such expression needs to be preceded by ;;:
;; print_int(l [1;2;3;4])
Another option is to make this toplevel expression a binding with
let () = print_int(l [1;2;3;4])
When parsing the code the parser advances until it hits l q. At this point there could be more arguments that should get applied to the function l. So the parser keeps going and the next thing it finds is the value print_int. Another argument to l. Which gives you your error.
The parser has no way of knowing that you had finished the code for the function l. In the top level the special token ;; is used to tell the parser that the input is finished and it should evaluate the code now. After that it starts paring the remaining input again.
Now why doesn't compiled code also have the ';;' token?
Simply because its not needed. In compiled code the line print_int(l [1;2;3;4]) is not valid input. That would be a statement you want to execute and functional languages have no such thing. Instead print_int(l [1;2;3;4]) is an expression that returns a value, () in this case, and you have to tell the compiler what to do with that value. A let () = tells the compiler to match it against (). And the let ... also tells the compiler that the previous let rec l ... has finished. So no special ;; token is needed.
Or think of it this way: In the top level there is an implicit let _ = if your input doesn't start with let. That way you can just type in some expression and see what it evaluates to without having to type let _ = every time. The ';;' token still means "evaluate now" though and is still needed.
I am following some tutorial I found on Rust, and I ran across something that my Java/C/C++ mind cannot comprehend:
impl fmt::Display for Matrix {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "({}, {})\n({}, {})", self.0, self.1, self.2, self.3)
}
}
I don't understand the lack of semicolon at the end of the write! macro call. I get an error from the compiler if I add it.
I am guessing that if the semicolon is not there then the Result from write! is used as return value of fmt, but can anybody provide a more specific explanation to why that is and if it always applies?
The write macro uses the write_fmt() method either from std::fmt::Write or from std::io::Write; both return Result<(), Error> and you need to omit the semicolon in order to have it as the output of fmt().
from The Rust Book, 1st edition:
Rust functions return exactly one value, and you declare the type
after an ‘arrow’, which is a dash (-) followed by a greater-than sign
(>). The last line of a function determines what it returns. You’ll
note the lack of a semicolon here. If we added it in we would
get an error.
This reveals two interesting things about Rust: it is an
expression-based language, and semicolons are different from
semicolons in other ‘curly brace and semicolon’-based languages.
I have code that does some parsing of files according to specified rules. The whole parsing takes place in a monad that is a stack of ReaderT/STTrans/ErrorT.
type RunningRule s a = ReaderT (STRef s LocalVarMap) (STT s (ErrorT String Identity)) a
Because it would be handy to run some IO in the code (e.g. to query external databases), I thought I would generalize the parsing, so that it could run both in Identity or IO base monad, depending on the functionality I would desire. This changed the signature to:
type RunningRule s m a = ReaderT (STRef s LocalVarMap) (STT s (ErrorT String m)) a
After changing the appropriate type signatures (and using some extensions to get around the types) I ran it again in the Identity monad and it was ~50% slower. Although essentially nothing changed, it is much slower. Is this normal behaviour? Is there some simple way how to make this faster? (e.g. combining the ErrorT and ReaderT (and possibly STT) stack into one monad transformer?)
To add a sample of code - it is a thing that based on a parsed input (given in C-like language) constructs a parser. The code looks like this:
compileRule :: forall m. (Monad m, Functor m) =>
-> [Data -> m (Either String Data)] -- For tying the knot
-> ParsedRule -- This is the rule we are compiling
-> Data -> m (Either String Data) -- The real parsing
compileRule compiled (ParsedRule name parsedlines) =
\input -> runRunningRule input $ do
sequence_ compiledlines
where
compiledlines = map compile parsedlines
compile (Expression expr) = compileEx expr >> return ()
compile (Assignment var expr) =
...
compileEx (Function "check" expr) = do
value <- expr
case value of
True -> return ()
False -> fail "Check failed"
where
code = compileEx expr
This is not so unusual, no. You should try using SPECIALIZE pragmas to specialize to Identity, and maybe IO too. Use -ddump-simpl and watch for warnings about rule left hand sides being too complicated. When specialization doesn't happen as it should, GHC ends up passing around typeclass dictionaries at runtime. This is inherently somewhat inefficient, but more importantly it prevents GHC from inlining class methods to enable further simplification.