Suppress "val it" output in Standard ML - sml

I'm writing a "script" in Standard ML (SML/NJ) that sets up the interactive environment to my liking. The last thing the script does is print out a message indicating everything went smoothly. Essentially, the last line is this:
print "SML is ready.\n";
When I run the script, all goes well but the SML interpreter displays the return value from the print function.
SML is ready.
val it = () : unit
-
Since I'm merely printing something to the screen, how can I suppress the "val it = () : unit" output so that all I see is the "SML is ready" message followed by the interpreter prompt?

To surpress the SML-NJ prompt and response, use the following assignment.
Compiler.Control.Print.out := {say=fn _=>(), flush=fn()=>()};
print "I don't show my type";
I don't show my type
although I don't see why the print function returning the type is bad.
The say function controls what is printed out.
There is a larger example in the following SML/NJ notes http://www.cs.cornell.edu/riccardo/prog-smlnj/notes-011001.pdf
The useSilently function can be used to load a file but without displaying any output
associated with the loading
fun useSilently (s) = let
val saved = !Compiler.Control.Print.out
fun done () = Compiler.Control.Print.out := saved
in
Compiler.Control.Print.out := {say = fn _ => (), flush = fn () => ()}
(use (s); done ()) handle _ => done ()
end
This is essentially changing the say function to do nothing and then setting it back at the end.

Use this:
val _ = print "I don't show my type";

In Moscow ML you can run the REPL without declaration output with
mosml -quietdec file.sml

Related

How can I generate code from file at compile time using a macro?

I have a CSV file that looks like this:
CountryCode,CountryName
AD,Andorra
AE,United Arab Emirates
AF,Afghanistan
AG,Antigua and Barbuda
// -- snip -- //
and a class that looks like this:
module OpenData
class Country
def initialize(#code : String, #name : String)
end
end
end
and I want to have a class variable within the module automatically loaded at compile time like this:
module OpenData
##countries : Array(Country) = {{ run "./sources/country_codes.cr" }}
end
I tried to use the "run" macro above with the following code:
require "csv"
require "./country"
content = File.read "#{__DIR__}/country-codes.csv"
result = [] of OpenData::Country
CSV.new(content, headers: true).each do |row|
result.push OpenData::Country.new(row["CountryCode"], row["CountryName"])
end
result
but this results in
##countries : Array(Country) = {{ run "./sources/country_codes.cr" }}
^
Error: class variable '##countries' of OpenData must be Array(OpenData::Country), not Nil
All my other attempts somehow failed due to various reasons, like not being able to call .new within a macro or stuff like that. This is something I regularly do in Elixir and other languages that support macros and is something I would suspect Crystal can also achieve... I'd also take any other way that accomplishes the task at compile time!
Basically there are several more files I want to process this way, and they`re longer/more complex... thanks in advance!
EDIT:
Found the issue. It seems that I have to return a string that includes actual crystal code from the "run" macro. So, the code in the "run" file becomes:
require "csv"
content = File.read "#{__DIR__}/country-codes.csv"
lines = [] of String
CSV.new(content, headers: true).each do |row|
lines << "Country.new(\"#{row["CountryCode"]}\", \"#{row["CountryName"]}\")"
end
puts "[#{lines.join(", ")}]"
and everything works!
You already found your answer, but for completeness, here are the docs, from: https://crystal-lang.org/api/1.2.2/Crystal/Macros.html#run%28filename%2C%2Aargs%29%3AMacroId-instance-method
Compiles and execute a Crystal program and returns its output
as a MacroId.
The file denoted by filename must be a valid Crystal program.
This macro invocation passes args to the program as regular
program arguments. The program must output a valid Crystal expression.
This output is the result of this macro invocation, as a MacroId.
The run macro is useful when the subset of available macro methods
are not enough for your purposes and you need something more powerful.
With run you can read files at compile time, connect to the internet
or to a database.
A simple example:
# read.cr
puts File.read(ARGV[0])
# main.cr
macro read_file_at_compile_time(filename)
{{ run("./read", filename).stringify }}
end
puts read_file_at_compile_time("some_file.txt")
The above generates a program that will have the contents of some_file.txt.
The file, however, is read at compile time and will not be needed at runtime.

variable type tagged additionally with Nil in ensure clause

I wonder why the type of the variable is (String | Nil) and not just String? Is there a way one can make it just String?
def main
text = "hello"
ensure
puts typeof(text) # => (String | Nil)
end
main
https://carc.in/#/r/2w3a
ensure runs after the main body in any case, even if there was an exception raised. Because this could have happend anywhere, it has to be considered that the body of the method hasn't been executed at all if it failed at the first instruction.
Therefore, in the ensure block, all variables are known but it must be assumed that their value can be nil.
If you're sure that text is always set, you don't need to protect that assignment in a rescue/ensure clause.
def main
text = "hello"
begin
# here is the code that might fail
ensure
puts typeof(text) # => String
end
end

How to save console output to string in crystal?

On ruby I can do
require "stringio"
def with_captured_stdout
begin
old_stdout = $stdout
$stdout = StringIO.new('','w')
yield
$stdout.string
ensure
$stdout = old_stdout
end
end
and later call it like
str = with_captured_stdout { Solution.main("Greetings from Javatlacati") }
but on crystal-lang I can refer to global variable $stdout without getting the corresponding error
$global_variables are not supported, use ##class_variables instead
is there any workaround? Thank you in advance.
Currently there's no easy way to capture stdout or stderr in the crystal standard library, however here's a shard which looks to do that: https://github.com/mosop/stdio.

verbose error with ocamlyacc

In bison, it is sufficient to add
%verbose-error
to the file to make the parser errors more verbose. Is there any way to gain similar functionality with ocamlyacc?
Here is the answer for a similar question, but I could not make anything out of it. This is how I call the lexer and parser functions:
let rec foo () =
try
let line = input_line stdin in
(try
let _ = (Parser.latexstatement lexer_token_safe (Lexing.from_string line)) in
print_string ("SUCCESS\n")
with
LexerException s -> print_string ("$L" ^ line ^ "\n")
| Parsing.Parse_error -> print_string ("$P" ^ line ^ "\n")
| _ -> print_string ("$S " ^ line ^ "\n"));
flush stdout;
foo ();
with
End_of_file -> ()
;;
foo ();;
I don't think that there's an option in ocamlyacc to do what you want automatically, so let me try to provide below a through description of what could be done to handle syntactic errors and have more useful messages. Maybe it is not what you asked.
Errors must actually be separated in lexical and parse errors, depending on which stage of the parsing process the error happens in.
In mll files, a Failure exception will be raised in case of unexpected patterns
in mly files, it's a Parsing.Parse_error exception which will be generated
So you have several solutions:
let the lexer and parser code raise their exceptions, and catch them in the code calling them
implement the specific cases of errors in the either of them with
a catch all rule for the lexer (or some more specific patterns if necessary)
using the error special terminal in the parser rules to catch errors in specific places
In any case, you will have to make functions to get information about the position of the error in the source.
Lexing and Parsing both use a location record, defined in Lexing, with the following fields:
pos_fname : the name of the file currently processed
pos_lnum : the line number in the file
pos_bol : the character number from the start of the file at the beginning of the line
pos_cnum : the character number at the current position
The lexbuf variable used by the lexer has two values like that to track the current token being lexed (lexeme_start_p and lexeme_curr_p in Lexing let you access these data). And the parser has four to track the current symbol (or non-terminal) about to be synthetized, and the current rule items, which can be retrieved with Parsing functions (rhs_start_pos and rhs_end_pos, as well as symbol_start_pos and symbol_end_pos).
Here's a few functions to generate more detailed exceptions:
exception LexErr of string
exception ParseErr of string
let error msg start finish =
Printf.sprintf "(line %d: char %d..%d): %s" start.pos_lnum
(start.pos_cnum -start.pos_bol) (finish.pos_cnum - finish.pos_bol) msg
let lex_error lexbuf =
raise ( LexErr (error (lexeme lexbuf) (lexeme_start_p lexbuf) (lexeme_end_p lexbuf)))
let parse_error msg nterm =
raise ( ParseErr (error msg (rhs_start_p nterm) (rhs_end_p nterm)))
and some basic use case:
parser:
%token ERR
/* ... */
wsorword:
WS { $1 }
| WORD { $1 }
| error { parse_error "wsorword" 1; ERR "" } /* a token needed for typecheck */
;
lexer:
rule lexer = parse
(* ... *)
(* catch all pattern *)
| _ { lex_error lexbuf }
All that would be left to do is to modify your top level function to catch the exceptions and process them.
Finally, for debugging purposes, there is a set_trace function available in Parsing which enable the display messages of the state machine used by the parsing engine: it traces all the internal state changes of the automaton.
In the Parsing module (you can check it here) there is the function Parsing.set_trace that will do just that. You can use it as:Parsing.set_trace True to enable. Also, you can run ocamlyacc with the -v argument and it will output a .output, listing all states and trasitions.

I am new to RUBY and i need to understand 3 functions

I have been given the 3 functions below. Can anybody please help me to understand these? I am trying to port an application to C++ using Qt, but I don't understand these functions. So please help me!
Thanks in advance.
function 1:
def read_key
puts "read pemkey: \"#{#pkey}\"" if #verbose
File.open(#pkey, 'rb') do |io|
#key = OpenSSL::PKey::RSA.new(io)
end
end
function 2:
def generate_key
puts "generate pemkey to \"#{#pkey_o}\"" if #verbose
#key = OpenSSL::PKey::RSA.generate(KEY_SIZE)
# save key
File.open(#pkey_o, 'wb') do |file|
file << #key.export()
end
end
function 3:
def sign_zip
puts "sign zip" if #verbose
plain = nil
File.open(#zip, 'rb') do |file|
plain = file.read
end
#sig = #key.sign(OpenSSL::Digest::SHA1.new, plain)
end
There are probably two things about the above code that are confusing you, which if clarified, will help understand it.
First, #verbose and #key are instance variables, what a C++ programmer might call "member variables." The "if #verbose" following the puts statement literally means only do the puts if #verbose is true. #verbose never needs to be declared a bool--you just start using it. If it's never initialized, it's "nil" which evaluates to false.
Second, the do/end parts are code blocks. Many Ruby methods take a code block and execute it with a variable declared in those pipe characters. An example would be "array.each do |s| puts s; end" which might look like "for(int i = 0; i < array.size(); ++i) { s = array[i]; puts(s); }" in C++. For File.open, |io| is the file instance opened, and "read" is one of its methods.
These are all methods. #{#pkey_o} is string interpolation, substituting in the contents of an instance variable (called pkey_o; Ruby instance variables begin with # and class variables – unused here – begin with ##).
File.open(#pkey, 'rb') do |io|
#key = OpenSSL::PKey::RSA.new(io)
end
That opens the file whose name is stored in #pkey, stores the file handle in io (a block-local variable) and uses that with OpenSSL::PKey::RSA.new, whose result is stored in #key. Finally, it closes the file handle when the block is finished (at the end) whether or not it is a successful exit or an error case (in which case an exception would be thrown, but it would still be thrown). When translating this to C++, use of the RAII pattern is entirely reasonable (if you were going to Java, I'd say to use try/finally).