Multiple statements in Main module - syntax-error

How do you put multiple lines of statements inside an Elm main module
Example,
module Main exposing (main)
import Html exposing (text)
main =
text "1"
text "2"
The above does not work and gives this error
Detected errors in 1 module.
-- TOO MANY ARGS -------------------------------------------------- src/Main.elm
The `text` function expects 1 argument, but it got 3 instead.
5|> text "1"
6| text "2"
Are there any missing commas? Or missing parentheses?
Putting parenthesis and commas does not help.

Elm is an expression-based language. It doesn't have statements because it doesn't have side-effects. Instead it consists of expressions which return values associated with types that are verified at compile-time.
Your code is a valid expression syntactically, so I'm not sure how you got that specific error. I can't reproduce it either directly at top level, where expressions don't belong, or in a function where expressions do belong, but there I get a type error instead of a syntax error. You're leaving out some essential part of your code.
In any case, even if you put it correctly into a function this won't do what you want. There are multiple problems even then:
Your code will be interpreted as three arguments applied to the function text, '1', text, and '2', because the line-break is not significant.
'1' is a character literal, not a string literal. "1" is a string literal.
Whatever you're going to use this with, it most likely expects a single element, not a list of elements.
The correct way to return two elements as one is to wrap the two elements in a parent element, like 'span' for example:
module Main exposing (main)
import Html exposing (text, span)
main =
span []
[ text "1"
, text "2"
]
Lastly, I recommend that you begin learning by following the official Elm guide. Elm is different enough that a trial-and-error approach based on what tends to work in JavaScript is likely to just lead to frustration.

Related

How to write xpath for following example?

For example, I have div tag that has two attributes.
class='hello#123' text='321#he#321llo#321'
<div> class='hello#123' text='321#he#321llo#321'></div>
Here, I want to write xpath for both class and text attributes but numbers may change dynamically. ie., "hello#123" may become "345" when we reload. "321#he#321llo#321" may become "567#he#456llo#321".
Note: Need to write xpath in single line not separately.
Assuming that you have the (corrected) two-attribute-HTML
<div class='hello#123' text='321#he#321llo#321'>...</div>
you can select it using the following, for example:
Using the contains() function
//div[contains(#class,'hello') and contains(#text,'#he#')]
This is quite specific and only applicable if the "hello" is always split in the same way
Using the translate() function to mask everything except the chars for "hello"
//div[translate(#class,'#0123456789','')='hello' and translate(#text,'#0123456789','')='hello']
This removes all # chars and digits and checks if the remaining string is "hello"
I guess combining these two approaches you will be able to create your own XPath expression fitting your needs. The patterns you provided were not fully clear, so this may only approach a good enough solution.

Confusing .fmt behavior with nested Lists

The docs say that fmt
Returns a string where each element in the list has been formatted according to $format [the first argument] and where each element is separated by $separator [the second argument].
Based on that description, I expected to be able to call .fmt on a List of Lists, and then pass a printf-style format string containing a % directive for each element in the inner list. But that doesn't work.
If you'd told me that I was wrong about ^^^^, I'd have expected that .fmt was auto-flattening its arguments and thus that each argument would be formatted and separated by the $separator. But that's also not what happens.
Instead, running this code
say (<a b c>, <1 2 3>, <X Y Z>).fmt('→%03s|', "\n=================\n");
produces this output:
→00a| →00b| →00c|
=================
→001| →002| →003|
=================
→00X| →00Y| →00Z|
That is, the format string is applied to each element in the inner lists, those lists are then stringified (without using the format string; note the between each | and → character), and then the separator is inserted between each outer list.
That leaves me with three questions:
Have I correctly described/understood the current behavior? [edit: nope. See below]
Is this behavior intentional or an odd bug? (I checked Roast, but didn't see anything either way)
Assuming this is intentional, why? Is there some way that this is consistent with Raku's general approach to handling lists that I'm missing? Or some other reason for this (imo) surprising behavior?
Edit:
After further investigation, I've realized that the behavior I observed above only occurs if the format string contains a width directive. Changing the →%03s| format string from above to →%s| produces the following output:
→a b c|
=================
→1 2 3|
=================
→X Y Z|
That is, without a width, the format string is applied after the list is stringified rather than before.
So I'm back to being confused/thinking at least some of this behavior must be buggy.
Ok, it looks like there were at least two bugs here. This should be fixed with https://github.com/rakudo/rakudo/commit/a86ec91e36 . Writing spectests for these situations, would be appreciated :-)

Dojo List Text Box automatic delimiter

When we started using a Dojo List Text Box in one of our applications, I came across the problem, that this Dojo control seems to have a built in delimiter, automatically splitting every String that contains a comma into extra array items.
A code to verify this behaviour:
<xe:djextListTextBox id="djextListTextBox1"></xe:djextListTextBox><xe:valuePicker id="valuePicker1" for="djextListTextBox1">
<xe:this.dataProvider>
<xe:simpleValuePicker>
<xe:this.valueList><![CDATA[11111
222,22
33333]]></xe:this.valueList>
</xe:simpleValuePicker>
</xe:this.dataProvider>
</xe:valuePicker>
I managed to resolve the situation by manually defining another delimiter
multipleSeparator="|"
which seems to overwrite the default delimiter, but I still would be very interested in verification of this finding and experts' tips on how to handle this control properly for future reference.
Yes, it uses "," as the default delimiter.
It is defined in the dojo widget source code of _ListTextBox.js (in com.ibm.xsp.extlib.controls package, \resources\web\extlib\dijit folder. This is the base widget for several components (e.g. ListTextBox, NameTextBox, etc.) and the multiple item seperator (msep) defaults to ",".
Basically, these components keep value in a hidden inputbox and submit that value. Internally, they convert the submitted value into a vector and store into the data binding. So as long as you don't have the declared delimiter in your value list, you may use any delimiter.
One problem I had is \n, because I experienced some problems in the past. Using ";" or "," is no problem with ListTextBox. However, NameTextBox doesn't work with any delimiter other than ",". No big deal, because it's only name elements. If you use ",", this component keeps values correctly but does not render well.

How to use Regular Expressions inside treePatterns?

I am working with the example about Parse Tree Matching and XPath shown here. More specifically, I was trying to understand how the following code works:
// assume we are parsing Java
ParserRuleContext tree = parser.compilationUnit();
String xpath = "//blockStatement/*"; // get children of blockStatement
String treePattern = "int <Identifier> = <expression>;";
ParseTreePattern p =
parser.compileParseTreePattern(treePattern,
ExprParser.RULE_localVariableDeclarationStatement);
List<ParseTreeMatch> matches = p.findAll(tree, xpath);
System.out.println(matches);
What I wanted to ask is if we can have regular expressions inside the treePattern string?
For example, I want to write a pattern which identifies all the localVariableDeclarations inside a for loop.
I would like to be able to identify the following code:
for (Object o : list) {
int tempVariable=0;
if ( o.id ==12) {
System.out.println(t);
}
}
The way I have written the pattern (which works) to identify this code is as follows:
String pattern3 = " for ( <className1:type> <localName1:Identifier> : <listName1:expression> ) { <localVariables1:localVariableDeclarationStatement> "
+ "if (<parameter1:expression>.<identifier1:Identifier> == <value1:primary> ) <block1:statement> }";
However, if I have more than one local variables, the pattern doesn't match. I tried to add a '*' at the end as it would happen in the grammar file, but I get an
* invalid tag error.
<localVariables1:localVariableDeclarationStatement>*
Of course I can also add a pattern with two localVariableDeclarationStatement statements, but this again means that I have to create many different patterns for each number of local variables that I want to identify:
<localVariables1:localVariableDeclarationStatement> <localVariables2:localVariableDeclarationStatement> and identify the pattern with
At this time, we don't support repeated elements within the patterns. I thought about that but it essentially means making yet another parser generator whereas static patterns like that are fairly easy to match. It's possible to build one of these, as the last version of ANTLR had tree grammars where you could in fact specify the grammatical structure of subtrees. Until we decide what sort of enhancement to the patterns we can make, I suggest you get creative.
In your specific case, find all of the localVariableDeclarations within for loops as you are doing now and then use a small bit of code to walk that list to identify the contiguous sequences (they are all siblings) and the ones terminated by that particular IF pattern. Would that work?

Get Text Symbol Programmatically With ID

Is there any way of programmatically getting the value of a Text Symbol at runtime?
The scenario is that I have a simple report that calls a function module. I receive an exported parameter in variable LV_MSG of type CHAR1. This indicates a certain status message created in the program, for instance F (Fail), X (Match) or E (Error). I currently use a CASE statement to switch on LV_MSG and fill another variable with a short description of the message. These descriptions are maintained as text symbols that I retrieve at compile time with text-MS# where # is the same as the possible returns of LV_MSG, for instance text-MSX has the value "Exact Match Found".
Now it seems to me that the entire CASE statement is unnecessary as I could just assign to my description variable the value of the text symbol with ID 'MS' + LV_MSG (pseudocode, would use CONCATENATE). Now my issue is how I can find a text symbol based on the String representation of its ID at runtime. Is this even possible?
If it is, my code would look cleaner and I wouldn't have to update my actual code when new messages are added in the function module, as I would simply have to add a new text symbol. But would this approach be any faster or would it in fact degrade the report's performance?
Personally, I would probably define a domain and use the fixed values of the domain to represent the values. This way, you would even get around the string concatenation. You can use the function module DD_DOMVALUE_TEXT_GET to easily access the language-dependent text of a domain value.
To access the text elements of a program, use a function module like READ_TEXT_ELEMENTS.
Be aware that generic programming like this will definitely slow down your program. Whether it would make your code look cleaner is in the eye of the beholder - if the values change rarely, I don't see why a simple CASE statement should be inferior to some generic text access.
Hope I understand you correctly but here goes. This is possible with a little trickery, all the text symbols in a report are defined as variables in the program (with the name text-abc where abc is the text ID). So you can use the following:
data: lt_all_text type standard table of textpool with default key,
lsr_text type ref to textpool.
"Load texts - you will only want to do this once
read textpool sy-repid into lt_all_text language sy-langu.
sort lt_all_Text by entry.
"Find a text, the field KEY is the text ID without TEXT-
read table lt_all_text with key entry = i_wanted_text
reference into lsr_text binary search.
If you want the address you can add:
field-symbols: <l_text> type any.
data l_name type string.
data lr_address type ref to data.
concatenate 'TEXT-' lsr_text->key into l_name.
assign (l_name) to <l_text>.
if sy-subrc = 0.
get reference of <l_text> into lr_address.
endif.
As vwegert pointed out this is probably not the best solution, for error handling rather use message classes or exception objects. This is useful in other cases though so now you know how.