Elm: How to log inside a foldl - elm

I have the following code:
findPerson name peeps = List.foldl
(\a b -> case b of
Just _ -> b
Nothing -> if a.name == name then
Just a
else Nothing
) Nothing peeps
I would like to log the values of a and b inside the foldl. I've tried:
findPerson : String -> List Person -> Maybe Person
findPerson name peeps = List.foldl
(\a b ->
Debug.log(a)
Debug.log(b)
case b of
Just _ -> b
Nothing -> if a.name == name then
Just a
else Nothing
) Nothing peeps
However, this throws an error
I am looking for one of the following things:
a closing paren ')'
whitespace`
What am I doing wrong, and how can I log the values inside foldl?

You can use a let in block for debugging.
let
_ = Debug.log "a" a
_ = Debug.log "b" b
in
case b of
...
A function (or lambda) can only return once.
Debug.log returns the second argument unchanged, so you have to pattern match it against something - and because you don't need the argument twice, but the side effect of Debug.log, you can pattern match it against _ (ignore).

You can also put the Debug.log directly inside the case statement, or inside the if statement for the same reasons #farmio mentioned :) - Like so :
findPerson name peeps = List.foldl
(\a b ->
case ( Debug.log "inspect b: " b ) of
Just _ ->
b
Nothing ->
if ( Debug.log "person name is: " a.name ) == name then
Just a
else
Nothing
) Nothing peeps
Not as clean, but sometimes more useful because is more compact.

Related

Nested inline if statement

In VB .Net it is possible to use inline If statements, like this
if a Then ret = "A" Else ret = "Not A"
I know it is also possible to nest these statements. I know this might not be good practice as readability drops down...
If a Then If b Then ret = "A & B" Else ret = "A & Not B" Else ret = "Not A"
which will be evaluated like this :
If a Then
If b Then
ret = "A & B"
Else
ret = "A & Not B"
End If
Else
ret = "Not A"
End If
Now if I remove the last Else statement, I get this :
If a Then If b Then ret = "A & B" Else ret = "A & Not B"
which is :
If a Then
If b Then
ret = "A & B"
Else
ret = "A & Not B"
End If
End If
So I guess the compiler finds the Else and matches it to the last openend If in the line, which makes sense.
My question is : Is it possible to change the evaluation order ? By that I mean is it possible that the Else is matched with the first if ?
So it would look like this :
If a Then
If b Then
ret = "A & B"
End If
Else
ret = "Not A"
End If
But inlined (something like this, parenthesis added to understand what I mean) :
If a Then ( If b Then ret = "A & B" ) Else ret = "Not A"
I tried with parenthesis or adding a End If but it provokes syntax errors, and I couldn't find documentation for this.
I'm not stuck anywhere and I know this might not be a good prorgamming practice, but I just wanted to know (out of curiosity) if it was possible.
I know also I could switch the statements (i.e. test b before a), but let's say I can't (a is a List and must be tested for Nothing before b which would be the Count for example).
You could do it like this
ret = If(a, If(b, "A & B", "A & Not B"), "Not A")
Personally, I never understood the need to put everything in one line.
You may find that this is what you need:
If a And B Then
ret = "A & B"
Else
ret = "Not A"
End If
Or as a single line:
If A And B Then Ret = "A & B" Else RET = "Not A"
I just created a simple console application with your final nested if statement and it worked fine
Sub Main()
Dim a = False
Dim b = True
If a Then
If b Then
Console.WriteLine("A & B")
End If
Else
Console.WriteLine("A & Not B")
End If
Console.ReadLine()
End Sub

Bound expressions inside a condition in a cond block in Elixir?

Is there any way to have multiple bound expressions in a condition in a cond block similar to:
cond do
a = 1; a * 2 == 2 -> "Yes"
end
?
I guess it would be possible if there were something in Elixir like "let in" binding expressions as in Haskell:
let a = 1 in a * 2
Update
In the case below I'd like to bind the String.replace expression to a variable to increase readability (I could of course do it outside the cond which isn't an optimal solution for obvious reasons). The condition checks if the input is upper case only (apart from non-alphabetic characters) and is taken from an exercism.io challenge:
String.upcase(String.replace(input, ~r/[^A-Za-z]/, "")) == String.replace(input, ~r/[^A-Za-z]/, "") and String.length(String.replace(input, ~r/[^A-Za-z]/, "")) > 0 -> "Whoa, chill out!"
To directly answer the first question, the answer is yes. Your original code:
cond do
a = 1; a * 2 == 2 -> "Yes"
end
Is parsed as:
cond do
a = 1
a * 2 == 2 -> "Yes"
end
Because ; means the end of the whole expression. In case you want to include multiple expressions, use parens:
cond do
(a = 1; a * 2 == 2) -> "Yes"
end
Regarding your original question, I think there's nothing wrong with extracting a variable here:
def myfun(input) do
sanitized = String.replace(input, ~r/[^A-Za-z]/, "")
cond do
String.upcase(sanitized) == sanitized and String.length(sanitized) > 0 -> "Whoa, chill out!"
true -> "Good job"
end
end
You could also use the match operator = inside the pattern, more specifically you can use it in place of the first occurrence, but I think it is uglier and harder to read:
def myfun(input) do
cond do
String.upcase(sanitized = String.replace(input, ~r/[^A-Za-z]/, "")) == sanitized and String.length(sanitized) > 0 -> "Whoa, chill out!"
true -> "Good job"
end
end
However your code can be improved by closely looking at the comparisons you are doing. To match the condition, the input string must consist of only uppercase and non-alphabetic characters, containing at least one uppercase character. Since you are already using regexes, here's one that will match all of this in a single check:
\A[^a-z]*[A-Z][^a-z]*\z
Explanation:
\A and \z match string boundaries, the entire string must fulfill the condition
[^a-z]* zero or more non-lowercase characters, followed by
[A-Z] an uppercase character somewhere in the string, followed by
[^a-z]* zero or more non-lowercase characters
Code:
def myfun(input) do
cond do
Regex.match?(~r/\A[^a-z]*[A-Z][^a-z]*\z/, input) -> "Whoa, chill out!"
true -> "Good job"
end
end

Iterate through LUA Table for string match

I'm trying to match two tables by string case in sensitive.
Example
[6] =
{
["itemName"] = [Ore],
["cleanName"] = [[Iron Ingot]],
["secs"] = 25004,
["gN"] = [[Luminary]],
["buyer"] = [[#Naptha42]],
["eventType"] = 15,
["timestampz"] = 1399514069,
["quantity"] = 100,
["soldAmount"] = 500,
["seller"] = [[#FataI]],
},
I'm trying to move items from the above table format into a new table, or filter them into a list.
g = e.cleanName
for k, v in pairs(savedTable.ALL_ITEMS) do searchTable[k] = v
if g == savedTable.ALL_ITEMS.cleanName then
table.insert(searchTable, savedTable.ALL_ITEMS)
end
end
The problem above is g never = that savedTable.
The table has a few thousand entries and I'm trying to display by search, I believe the best way is to create a new table with the values im looking for?
Or is there a way to use the string.match to iterate through the table and display (print) only these values.
//Update
I have an active search, each time the user enters a letter it will search the table.
Example.
Val1 = "Hello"
Val2 = "Goodbye"
Val3 = "Hi"
While searching and the user enters "H" or "h" I want the results for "hello, hi" to show up but not "goodbye"
so with the if g == string.match(savedTable.ALL_ITEMS.cleanName)
not sure if that is correct.
//UPDATE for solution of what worked (thanks ESOUI)
local searchForItem = string.lower(g)
for k, v in ipairs(myTable.ALL_SALES) do
-- if string.lower(g) == string.lower(v.cleanName) then
if string.lower(v.cleanName):find(searchForItem) then
if v.cleanName ~= nil then
table.insert(searchTable, v)
end
end
end
If ALL_ITEMS is a table that contains tables then it isn't ever going to have a cleanName field directly.
Is that == in the loop intended to be against v?
Also, if ALL_ITEMS is integer indexed you probably want ipairs instead of pairs to walk the table in order.
Why are you inserting every element into searchTable (via searchTable[k] = v) and then also attempting to insert the matching entries again (via table.insert)?
You can use string.match to match g against the cleanName in your loop if you need to but that isn't going to solve the problem if you aren't comparing what you think you are comparing.

Linq test for null or empty fields

This is what I have tried
Dim B = (From r In _db.Personnel _
Where !(r.BldgDist.Trim() = String.Empty) _
Order By r.BldgDist _
Select r.BldgDist).ToList().Distinct()
For Each ab In B
list.Add(New ListItem(ab.BldgDist, ab.BldgDist))
Next
But at the bang it tells me that an identifier is expected. Not sure I understand what is missing. I am just trying to eliminate the null values and empty string values, before I load into a list.
Any help is appreciated. Thanks
VB.Net doesn't recognize ! but you can use the <> or Not operator instead.
Dim B = (From r In _db.Personnel _
Where (r.BldgDist.Trim() <> String.Empty) _
...
! is a C# operator, not VB. Use Not instead (or <>). For example:
Where Not (r.BldgDist.Trim() = String.Empty)
Or
Where r.BldgDist.Trim() <> String.Empty

Lua Script Pattern Matching Problem

First of all, I have been using this site as a reference through the entire scripting process and it has been wonderful. I appreciate how useful and knowledgeable everyone is here. With that in mind, I have a question regarding matching (pattern matching) in Lua. I am writing a script that essentially takes input from a file and imports it into a table. I am checking for specific MAC addresses in the file as the host I am querying.
if macFile then
local file = io.open(macFile)
if file then
for line in file:lines() do
local f = line
i, j = string.find ( f, "%x+" )
m = string.sub(f, i, j)
table.insert( macTable, m )
end
file:close()
end
This parses the file into a format I will use to query later. Once the table is built, I run a pattern matching sequence to try and match the MAC from the table by iterating the table and matching the pattern against the current iteration:
local output = {}
t = "00:00:00:00:00:00"
s = string.gsub( t, ":", "")
for key,value in next,macTable,nil do
a, p = string.find ( s, value )
matchFound = string.sub(s, a, p)
table.insert( output, matchFound )
end
This doesn't return any output although when I enter it line by line in a Lua prompt, it seems to work. The variables are being passed correctly I believe. Any suggestions?
If your macFile uses a structure like this:
012345678900
008967452301
000000000000
ffffffffffff
The following script should work:
macFile = "./macFile.txt"
macTable = {}
if macFile then
local hFile = io.open(macFile, "r")
if hFile then
for line in hFile:lines() do
local _,_, sMac = line:find("^(%x+)")
if sMac then
print("Mac address matched: "..sMac)
table.insert(macTable, sMac)
end
end
hFile:close()
end
end
local output = {}
t = "00:00:00:00:00:00"
s = string.gsub( t, ":", "")
for k,v in ipairs(macTable) do
if s == v then
print("Matched macTable address: "..v)
table.insert(output, v)
end
end
I am just leaving from work and can't have a deeper look at your problem right now, but the next two lines seem quite odd.
t = "00:00:00:00:00:00"
s = string.gsub( t, ":", "")
Basically you are removing all the ':' characters in the string t. Afterwards you end up with s being "000000000000". This is probably not what you want?