How to make uppercase records in purescript? - record

I have an API that forces me to return a JSON in the form of
{ Field1: "something"
, Field2: 12 }
However, I have failed to model this in Purescript so far.
I understand that the purescript grammar sees the upper case field names and thinks it is the type of a field without a field name. So I it is not straight forward to just encode a function like
test :: Number -> { Field1 :: String, Field2 :: Number }
Without resorting to using external javascript functions to change the object into something else, is it at all possible to construct a record with upper case field names in purescript? And if so, how?

Absolutely! PureScript allows any field names, not just "valid identifier" ones. You just have to double-quote them if they're weird:
x :: { "Field1" :: String, "Field2" :: String, "🍕" :: String }
x = { "Field1": "foo", "Field2": "bar", "🍕": "yum" }
y :: String
y = x."🍕"
Basically same deal as in JavaScript.

Related

How do I replace letters with numbers using the replace function in kotlin inside a lambda expression

mood = "leet"
modifier = { message ->
val regex = """(L|e|t)""".toRegex()
//Clueless about what to do after this
}
THIS IS WHAT I CAME UP WITH SO FAR, THE QUESTION IN THE BOOK BIG NERD RANCH KOTLIN EDITION 2 SAYS "leet (or 1337): The narrator will speak in leetspeak, replacing letters with numbers and symbols that look similar. For example, ‘L’ becomes ‘1’; ‘E’ becomes ‘3’; ‘T’ becomes ‘7’. (Hint: Take a look at String’s replace function. There is a version that accepts a lambda as the second parameter.)"
This is the function they're telling you to look at, specifically this one:
inline fun CharSequence.replace(
regex: Regex,
noinline transform: (MatchResult) -> CharSequence
): String
Returns a new string obtained by replacing each substring of this char sequence that matches the given regular expression with the result of the given function transform that takes MatchResult and returns a string to be used as a replacement for that match.
So the lambda you provide is a function that takes a MatchResult
and does something with it, and returns a CharSequence (which can be a one-character long String). The replace function calls that lambda for every match that regex makes.
You get the general idea of what you're supposed to do? You have two parts here - the thing that identifies parts of the input string to process, and the thing that takes those matches and changes them into something else. The result is the original string with those changes made. So you need to come up with a regex and a transform that work together.
Nobody (probably) is going to tell you the answer because the point is figuring it out for yourself, but if you have any questions about things like regexes people will be happy to help you out! And speaking of, this site is extremely useful (I just used it myself to check I knew what I was doing): https://regex101.com/
Here is the implementation as pointed by #cactustictacs :
5 -> {
mood = "leet"
val regex: Regex = """[LET]""".toRegex()
modifier = { message ->
message.uppercase().replace(regex) { m ->
when (m.value) {
"L" -> "1"
"E" -> "3"
"T" -> "7"
else -> ""
}
}
}
}
and here is the another method almost same but with minor change using regex.replace()
5 -> {
mood = "leet"
val regex: Regex = """[LET]""".toRegex()
modifier = { message ->
regex.replace(message.uppercase()){m ->
when (m.value) {
"L" -> "1"
"E" -> "3"
"T" -> "7"
else -> ""
}
}
}
}
You can use it in place of m to make it slightly more concise.

Perl6 Regex Match Num

I would like to match any Num from part of a text string. So far, this (stolen from from https://docs.perl6.org/language/regexes.html#Best_practices_and_gotchas) does the job...
my token sign { <[+-]> }
my token decimal { \d+ }
my token exponent { 'e' <sign>? <decimal> }
my regex float {
<sign>?
<decimal>?
'.'
<decimal>
<exponent>?
}
my regex int {
<sign>?
<decimal>
}
my regex num {
<float>?
<int>?
}
$str ~~ s/( <num>? \s*) ( .* )/$1/;
This seems like a lot of (error prone) reinvention of the wheel. Is there a perl6 trick to match built in types (Num, Real, etc.) in a grammar?
If you can make reasonable assumptions about the number, like that it's delimited by word boundaries, you can do something like this:
regex number {
« # left word boundary
\S+ # actual "number"
» # right word boundary
<?{ defined +"$/" }>
}
The final line in this regex stringifies the Match ("$/"), and then tries to convert it to a number (+). If it works, it returns a defined value, otherwise a Failure. This string-to-number conversion recognizes the same syntax as the Perl 6 grammar. The <?{ ... }> construct is an assertion, so it makes the match fail if the expression on the inside returns a false value.

Perl6 optional function flags

How can I implement functions that take an optional flag in Perl6? For example, say that I want to invoke my function like this:
format 'a b c';
or like this:
format :pretty 'a b c';
How can I do this? Thanks
It's just a named argument, in case of flags a boolean one. This all works out because :pretty is syntactic sugar for the pair :pretty(True) aka pretty => True.
You can either use the boolean value
sub format($arg, Bool :$pretty = False) {
if $pretty { ... }
else { ... }
}
or use its presence for multi-dispatch
multi format($arg) { ... }
multi format($arg, Bool :$pretty!) { ... }
In the first example, we provided a default value (which isn't really necessary as the undefined value boolifies to False, but it's arguably the 'right thing to do' semantically), in the second one we made it a required parameter by adding the !.
Also note that named arguments still have to be separated by commas, ie you'd use it as
format :pretty, 'a b c';
If you really want that odd syntax, you can use an operator and some subsignature magic. The Bool method is optional and the class Pretty can be empty. It's just there to provide something for the MMD-dispatcher to hold onto.
class Pretty { method Bool {True} };
sub prefix:<:pretty>(|c){ Pretty.new, c };
multi sub format((Pretty:D $pretty, |a)){ dd $pretty.Bool, a };
multi sub format(|c){ dd c };
format :pretty 'a b c'; format 'a b c';
# OUTPUT«Bool::True␤\(\("a b c"))␤\("a b c")␤»

ANTLR4 change listener during parse

I have an ANTLR4 listener which handles a standard and well-formed grammar, however am struggling with how to deal the non-standard implementations. Although all of the variants go through the lexer without problems the parse stage is a lot trickier.
A traditional way of doing this would be something like
// Header of document
variant = STANDARD;
if (header.indexOf("microsoft") != -1) {
variant = MICROSOFT;
} else if (header.indexOf("google") != -1) {
variant = GOOGLE;
}
...
// Parsing a particular element
if (variant.equals(MICROSOFT)) {
// Microsoft-specific stuff
} else if (variant.equals(GOOGLE)) {
// Google-specific stuff
} else {
// Standard stuff
}
but this quickly becomes unmaintainable. The obvious solution is to have a ParseTreeListener for the standard implementation and then subclass it for each variant, but I don't know which variant it is until I've started the parse.
So how can I either switch from one listener to another part-way through the parse, or restart the parse with a new listener once I know which variant I'm dealing with?
If these variants occur frequently, you might want to consider embedding custom code to handle context sensitive parsing by using predicates (the {...}? construct in the following pseudo grammar):
rule
: { boolean-expression-a }? a-alternative
| { boolean-expression-b }? b-alternative
| /* fall through */ not-a-or-b-alternative
;
Let's say you want to parse a file containing chunks. A chunk consists of a header and a data row. In the header you can set your variant. The data of a normal variant contains 3 NUMBERs, Google's variant contains 2 NUMBERs and Microsoft's variant contains a single NUMBER. An example of such a file would look like this:
header: none
data: 1 2 3
header: google
data: 4 5
header: microsoft
data: 6
And here's a demo of a context sensitive ANTLR v4 grammar able to parse this:
grammar T;
#parser::members {
enum Variant {
GOOGLE,
MICROSOFT,
OTHER;
public static Variant tryValueOf(String name) {
try {
return Variant.valueOf(name.toUpperCase());
}
catch(Exception e) {
return OTHER;
}
}
}
private Variant variant = Variant.OTHER;
}
parse
: chunk+ EOF
;
chunk
: header data
;
header
: K_HEADER COLON NAME {variant = Variant.tryValueOf($NAME.text);}
;
data
: {variant == Variant.MICROSOFT}? K_DATA COLON NUMBER #MicrosoftData
| {variant == Variant.GOOGLE}? K_DATA COLON NUMBER NUMBER #GoogleData
| K_DATA COLON NUMBER NUMBER NUMBER #OtherData
;
K_DATA : 'data';
K_HEADER : 'header';
NAME : [a-zA-Z]+;
NUMBER : [0-9]+;
COLON : ':';
SPACE : [ \t\r\n] -> skip;
Resulting in the following parse:

Determine type of a variable in Tcl

I'm looking for a way to find the type of a variable in Tcl. For example if I have the variable $a and I want to know whether it is an integer.
I have been using the following so far:
if {[string is boolean $a]} {
#do something
}
and this seems to work great for the following types:
alnum, alpha, ascii, boolean, control, digit, double, false, graph, integer, lower, print, punct, space, true, upper, wordchar, xdigit
However it is not capable to tell me if my variable might be an array, a list or a dictionary. Does anyone know of a way to tell if a variable is either of those three?
Tcl's variables don't have types (except for whether or not they're really an associative array of variables — i.e., using the $foo(bar) syntax — for which you use array exists) but Tcl's values do. Well, somewhat. Tcl can mutate values between different types as it sees fit and does not expose this information[*]; all you can really do is check whether a value conforms to a particular type.
Such conformance checks are done with string is (where you need the -strict option, for ugly historical reasons):
if {[string is integer -strict $foo]} {
puts "$foo is an integer!"
}
if {[string is list $foo]} { # Only [string is] where -strict has no effect
puts "$foo is a list! (length: [llength $foo])"
if {[llength $foo]&1 == 0} {
# All dictionaries conform to lists with even length
puts "$foo is a dictionary! (entries: [dict size $foo])"
}
}
Note that all values conform to the type of strings; Tcl's values are always serializable.
[EDIT from comments]: For JSON serialization, it's possible to use dirty hacks to produce a “correct” serialization (strictly, putting everything in a string would be correct from Tcl's perspective but that's not precisely helpful to other languages) with Tcl 8.6. The code to do this, originally posted on Rosetta Code is:
package require Tcl 8.6
proc tcl2json value {
# Guess the type of the value; deep *UNSUPPORTED* magic!
regexp {^value is a (.*?) with a refcount} \
[::tcl::unsupported::representation $value] -> type
switch $type {
string {
# Skip to the mapping code at the bottom
}
dict {
set result "{"
set pfx ""
dict for {k v} $value {
append result $pfx [tcl2json $k] ": " [tcl2json $v]
set pfx ", "
}
return [append result "}"]
}
list {
set result "\["
set pfx ""
foreach v $value {
append result $pfx [tcl2json $v]
set pfx ", "
}
return [append result "\]"]
}
int - double {
return [expr {$value}]
}
booleanString {
return [expr {$value ? "true" : "false"}]
}
default {
# Some other type; do some guessing...
if {$value eq "null"} {
# Tcl has *no* null value at all; empty strings are semantically
# different and absent variables aren't values. So cheat!
return $value
} elseif {[string is integer -strict $value]} {
return [expr {$value}]
} elseif {[string is double -strict $value]} {
return [expr {$value}]
} elseif {[string is boolean -strict $value]} {
return [expr {$value ? "true" : "false"}]
}
}
}
# For simplicity, all "bad" characters are mapped to \u... substitutions
set mapped [subst -novariables [regsub -all {[][\u0000-\u001f\\""]} \
$value {[format "\\\\u%04x" [scan {& } %c]]}]]
return "\"$mapped\""
}
Warning: The above code is not supported. It depends on dirty hacks. It's liable to break without warning. (But it does work. Porting to Tcl 8.5 would require a tiny C extension to read out the type annotations.)
[*] Strictly, it does provide an unsupported interface for discovering the current type annotation of a value in 8.6 — as part of ::tcl::unsupported::representation — but that information is in a deliberately human-readable form and subject to change without announcement. It's for debugging, not code. Also, Tcl uses rather a lot of different types internally (e.g., cached command and variable names) that you won't want to probe for under normal circumstances; things are rather complex under the hood…
The other answers all provide very useful information, but it's worth noting something that a lot of people don't seem to grok at first.
In Tcl, values don't have a type... they question is whether they can be used as a given type. You can think about it this way
string is integer $a
You're not asking
Is the value in $a an integer
What you are asking is
Can I use the value in $a as an integer
Its useful to consider the difference between the two questions when you're thinking along the lines of "is this an integer". Every integer is also a valid list (of one element)... so it can be used as either and both string is commands will return true (as will several others for an integer).
If you want to deal with JSON then I highly suggest you read the JSON page on the Tcl wiki: http://wiki.tcl.tk/json.
On that page I posted a simple function that compiles Tcl values to JSON string given a formatting descriptor. I also find the discussion on that page very informative.
For arrays you want array exists
for dicts you want dict exists
for a list I don't think there is a built in way prior to 8.5?, there is this from http://wiki.tcl.tk/440
proc isalist {string} {
return [expr {0 == [catch {llength $string}]}]
}
To determine if a variable is an array:
proc is_array {var} {
upvar 1 $var value
if {[catch {array names $value} errmsg]} { return 1 }
return 0
}
# How to use it
array set ar {}
set x {1 2 3}
puts "ar is array? [is_array ar]"; # ar is array? 1
puts "x is array? [is_array x]"; # x is array? 0
For the specific case of telling if a value is usable as a dictionary, tcllib's dicttool package has a dict is_dict <value> command that returns a true value if <value> can act as one.