What is the meaning of alias "#" in GF? - gf

I have encountered alias sign inside RGL in this operation:
mkRoot3 : Str -> Root3 = \fcl -> case fcl of {
f#? + c#? + l => {f = f ; c = c ; l = l} ;
_ => error ("mkRoot3: too short root" ++ fcl)
} ;
What does it mean, and what's the use of it?

The character # is used in pattern matching. The expression foo#bar means that you match something with the regex bar, and bind the result to variable foo.
Let's first recap some ways you can pattern match a string without #:
example1 : Str -> Str = \s -> case s of {
"x" => "the string is exactly x" ;
"x" + _ => "the string starts with x" ;
? => "the string is one character long" ;
? + ? => "the string is two characters long" ;
("a"|"i"|"u") => "the string is a vowel" ;
_ => "whatever, I'm bored"
} ;
In all of these, we are not reusing the string in the right-hand side. If you want to do that, you can just bind it into a variable, like this—not yet using # , because we are simply matching the start and the end of a string:
example2 : Str -> Str = \s -> case s of {
"x" + rest => "the string starts with x and ends with" ++ rest ;
start + "x" => "the string starts with" ++ start ++ "and ends with x" ;
_ => "..." } ;
Finally, if you want to match something to a regular expression and use whatever matches the regex on the RHS, now you need to use #:
example3 : Str -> Str = \s -> case s of {
v#("a"|"i"|"u") => "the string is the vowel" ++ v ;
a#? => "the string is one character long:" ++ a ;
a#? + b#? => "the string is two characters long:" ++ a ++ "followed by" ++ b ;
_ => "..." } ;
If you just tried to match a + b => … , or any other pattern that only contains variables, it wouldn't match words that are exactly 2 characters long. Instead it would just match empty string to one of them and the full string to the other.
So matching the regex ?, which matches exactly one character, and then binding the result to a variable, is the only way you can match something with exact length, and then reuse the matched character/string on the right-hand side.
You can read more on pattern matching at http://www.grammaticalframework.org/doc/gf-refman.html#pattern-matching .

Related

Building string from list of list of strings

I rather have this ugly way of building a string from a list as:
val input = listOf("[A,B]", "[C,D]")
val builder = StringBuilder()
builder.append("Serialized('IDs((")
for (pt in input) {
builder.append(pt[0] + " " + pt[1])
builder.append(", ")
}
builder.append("))')")
The problem is that it adds a comma after the last element and if I want to avoid that I need to add another if check in the loop for the last element.
I wonder if there is a more concise way of doing this in kotlin?
EDIT
End result should be something like:
Serialized('IDs((A B,C D))')
In Kotlin you can use joinToString for this kind of use case (it deals with inserting the separator only between elements).
It is very versatile because it allows to specify a transform function for each element (in addition to the more classic separator, prefix, postfix). This makes it equivalent to mapping all elements to strings and then joining them together, but in one single call.
If input really is a List<List<String>> like you mention in the title and you assume in your loop, you can use:
input.joinToString(
prefix = "Serialized('IDs((",
postfix = "))')",
separator = ", ",
) { (x, y) -> "$x $y" }
Note that the syntax with (x, y) is a destructuring syntax that automatically gets the first and second element of the lists inside your list (parentheses are important).
If your input is in fact a List<String> as in listOf("[A,B]", "[C,D]") that you wrote at the top of your code, you can instead use:
input.joinToString(
prefix = "Serialized('IDs((",
postfix = "))')",
separator = ", ",
) { it.removeSurrounding("[", "]").replace(",", " ") }
val input = listOf("[A,B]", "[C,D]")
val result =
"Serialized('IDs((" +
input.joinToString(",") { it.removeSurrounding("[", "]").replace(",", " ") } +
"))')"
println(result) // Output: Serialized('IDs((A B,C D))')
Kotlin provides an extension function [joinToString][1] (in Iterable) for this type of purpose.
input.joinToString(",", "Serialized('IDs((", "))')")
This will correctly add the separator.

How to change equal (=) to not equal to (<>) in postgres using Go

I have two sql querys that are very similar. The only difference is that in one of the WHERE clauses I am using equal to (=) instead of not equal to (<>). Is there a way to modify the query programmatically in an elegant way? I am looking for something like this:
func getEvents(name string, exclude bool) {
q := `SELECT * FROM events WHERE name`
if exclude {
q = q + " <> "
} else {
q = q + " = "
}
q = q + "$1"
result, err := DBQuery(q, name)
...
}
One elegant way would be to create a type and constants for the operators:
type Op string
const (
OpEqual Op = "="
OpNotEqual Op = "<>"
OpLessThan Op = "<"
OpGreaterThan Op = ">"
// ... any other ops you need
)
And then building the query string is a simple string concatenation:
q := "SELECT * FROM events WHERE name" + op + "$1"
Or you may use fmt.Sprintf():
q := fmt.Sprintf("SELECT * FROM events WHERE name %s $1", op)
Of course change signature of getEvents() to:
func getEvents(name string, op Op)
And calling getEvents() is now even nicer:
getEvents("error", OpEqual)
getEvents("error", OpNotEqual)
Try the examples on the Go Playground.

how to remove all html characters in snowflake, dont want to include all html special characters in query (no hardcoding)

Want to remove below kind of characters from string..pl help
'
&
You may try this one to remove any HTML special characters:
select REGEXP_REPLACE( 'abc&def³»ghi', '&[^&]+;', '!' );
Explanation:
REGEXP_REPLACE uses regular expression to search and replace. I search for "&[^&]+;" and replace it with "!" for demonstration. You can of course use '' to remove them. More info about the function:
https://docs.snowflake.com/en/sql-reference/functions/regexp_replace.html
About the regular expression string:
& is the & character of a HTML special character
[^&] means any character except &. Tthis prevents to REGEXP to replace all characters between the first '&' char and last ';'. It will stop when it see second '&'
+ means match 1 or more of preceding token (any character except &)
; is the last character of a HTML special character
CREATE or REPLACE FUNCTION UDF_StripHTML(str varchar)
returns varchar
language javascript
strict
as
'var HTMLParsedText=""
var resultSet = STR.split(''>'')
var resultSetLength =resultSet.length
var counter=0
while(resultSetLength>0)
{
if(resultSet[counter].indexOf(''<'')>0)
{
var value = resultSet[counter]
value=value.substring(0, resultSet[counter].indexOf(''<''))
if (resultSet[counter].indexOf(''&'')>=0 && resultSet[counter].indexOf('';'')>=0)
{
value=value.replace(value.substring(resultSet[counter].indexOf(''&''), resultSet[counter].indexOf('';'')+1),'''')
}
}
if (value)
{
value = value.trim();
if(HTMLParsedText === "")
{
HTMLParsedText = value
}
else
{
if (value) {
HTMLParsedText = HTMLParsedText + '' '' + value
}
}
value=''''
}
counter= counter+1
resultSetLength=resultSetLength-1
}
return HTMLParsedText';
to call this UDF :
Select UDF_StripHTML(text)

Elm - mapping a list and appending string to the end of each item

I'm learning Elm and trying to understand how to append a string to all items in a list, but at the end of each entry rather than the beginning. Sorry for the n00b question but I've read through all the docs/examples around List.map, String (.append, .join) and can't seem to find an answer.
e.g.
--create username list
usernames = ["Dave", "Simon", "Sally", "Joe"]
--create confirmExit function
confirmExit name = String.append " has left the room" name
--apply confirmExit function to all items in username list
List.map (\x -> confirmExit x) usernames
Gives me:
["has leftDave","has leftSimon","has leftSally","has leftJoe"] : List String
But how would I make it so that it returned:
["Dave has left","Simon has left","Sally has left","Joe has left"] : List String
Is there an equivalent of .append to add to the end instead of the beginning? Please?!
You just have the parameters reversed, try:
confirmExit name = String.append name " has left the room"
From the docs:
append : String -> String -> String
Append two strings. You can also
use the (++) operator to do this.
append "butter" "fly" == "butterfly"
So you could also use:
confirmExit name = name ++ " has left the room"
Which is possibly a bit more readable

Elm: How to pretty print the model in the browser?

This question is kind of silly but i didn't find a straight forward solution.
Assuming I have a model that resembles this: - at least this big.
initModel =
{ selectedCategory = "Vacantion"
, context = "root/Work"
, abstractSyntaxTree =
[ { categoryName = "Work"
, categoryContent =
[]
}
, { categoryName = "Vacation"
, categoryContent =
[ { folderName = "Hawaii"
, folderContent =
FolderContent
( [ { folderName = "Booking"
, folderContent = FolderContent ( [], [] )
}
]
, [ "flightTicket.jpg" ]
)
}
]
}
]
}
Question: How can i display it in the browser so that it looks good? - nothing fancy - just to see what's happening like a quick debugger..
What I've tried so far:
view =
div []
[ pre [style [("width", "300") ] ] [ text (toString model)]
]
Works great on smaller models but on this case, I get this long -single line - formatted json like structure:
I think this is the Problem: The prettify extension i installed in google chrome doesn't know how to deal with strings that do not contain \n in them. To check for this, i manually added a \n - and that string was split on the second row, as expected.
The output form text (toSting model) - it's a string that has no \n in it - so that's why everything is displayed on a single line in the browser - regardless of the 300 px limit on width.
Splitting up the string - by adding \n by myself - works except i don't know where exactly to add the \n. To make it dynamic, this requires a full-flagged parser for the model. A way to know where the expression starts, where is the next matching bracket .. etc. I'm not good enough to build this parser. I feel i'm over complicating this stuff. Must be a better solution..
How do you folks do it?
Elm does not allow you to enumerate over the items in a record. For type-safety no doubt. So there is no "clean" way to do display a record nicely.
UPDATE: The solution below will not work anymore as of Elm 0.19.
It relies on a (deprecated) function toString that would convert any type into a string.
Since Elm 0.17 (when I made this), Elm had already released a great debugger in 0.18, which already has a feature to follow model and messages in a separate window.
For debugging, you can do some trickery with toString to print it more neatly.
Below is example code, which you can copy/ paste to elm-lang.org/try.
Simply pass any record to the viewModel function, and it displays it in the browser.
It is quite crude, and probably not very performant with large records, but it will do the job..
import Html exposing (Html, text, div, p, pre)
import Html.Attributes exposing (style)
import String
quote = "\""
indentChars = "[{("
outdentChars = "}])"
newLineChars = ","
uniqueHead = "##FORMAT##"
incr = 20
model =
{ name = "Abe"
, age = 49
, someTuple = (18,49)
, relatives = [ "Claire", "Bill" ]
, comments = "any special characters like []{}, will not be parsed"
, cars = [ { brand = "BMW", model = "535i" } ]
}
viewModel : a -> Html msg
viewModel model =
let
lines =
model
|> toString
|> formatString False 0
|> String.split uniqueHead
in
pre [] <| List.map viewLine lines
viewLine : String -> Html msg
viewLine lineStr =
let
(indent, lineTxt) = splitLine lineStr
in
p [ style
[ ("paddingLeft", px (indent))
, ("marginTop", "0px")
, ("marginBottom", "0px")
]
]
[ text lineTxt ]
px : Int -> String
px int =
toString int
++ "px"
formatString : Bool -> Int -> String -> String
formatString isInQuotes indent str =
case String.left 1 str of
"" -> ""
firstChar ->
if isInQuotes then
if firstChar == quote then
firstChar
++ formatString (not isInQuotes) indent (String.dropLeft 1 str)
else
firstChar
++ formatString isInQuotes indent (String.dropLeft 1 str)
else
if String.contains firstChar newLineChars then
uniqueHead ++ pad indent ++ firstChar
++ formatString isInQuotes indent (String.dropLeft 1 str)
else if String.contains firstChar indentChars then
uniqueHead ++ pad (indent + incr) ++ firstChar
++ formatString isInQuotes (indent + incr) (String.dropLeft 1 str)
else if String.contains firstChar outdentChars then
firstChar ++ uniqueHead ++ pad (indent - incr)
++ formatString isInQuotes (indent - incr) (String.dropLeft 1 str)
else if firstChar == quote then
firstChar
++ formatString (not isInQuotes) indent (String.dropLeft 1 str)
else
firstChar
++ formatString isInQuotes indent (String.dropLeft 1 str)
pad : Int -> String
pad indent =
String.padLeft 5 '0' <| toString indent
splitLine : String -> (Int, String)
splitLine line =
let
indent =
String.left 5 line
|> String.toInt
|> Result.withDefault 0
newLine =
String.dropLeft 5 line
in
(indent, newLine)
main =
viewModel model
By now we have a nice package for 0.19.
elm install ThinkAlexandria/elm-pretty-print-json
And run
json = """{"name": "Arnold", "age": 70, "isStrong": true,"knownWeakness": null,"nicknames": ["Terminator", "The Governator"],"extra": {"foo": "bar","zap": {"cat": 1,"dog": 2},"transport": [[ "ford", "chevy" ],[ "TGV", "bullet train", "steam" ]]}}"""
{-| Formating configuration.
`indent` is the number of spaces in an indent.
`columns` is the desired column width of the formatted string. The formatter
will try to fit it as best as possible to the column width, but can still
exceed this limit. The maximum column width of the formatted string is
unbounded.
-}
config = {indent = 4, columns = 80}
-- run prettifier
Result.withDefault "" (Json.Print.prettyString config json)
-- result
{-
{
"extra": {
"transport": [
[
"ford",
"chevy"
],
[
"TGV",
"bullet train",
"steam"
]
],
"zap": {
"dog": 2,
"cat": 1
},
"foo": "bar"
},
"nicknames": [
"Terminator",
"The Governator"
],
"knownWeakness": null,
"isStrong": true,
"age": 70,
"name": "Arnold"
}
-}
I found this in slack : elm-debug-transformer
Not rely what i asked for, because for example im gonna need to make it work with node.js also, but still seems like good solution for now.