How to access shadowed DXL variables/functions? - ibm-doors

I encountered an error in a script I was debugging because somebody had created a variable with a name matching a built-in function, rendering the function inaccessible. I got strange errors when I tried to use the function, like:
incorrect arguments for (-)
incorrect arguments for (by)
incorrect arguments for ([)
incorrect arguments for (=)
Example code:
int length
// ...
// ...
string substr
string str = "big long string with lots of text"
substr = str[0:length(str)-2]
Is there a way to access the original length() function in this situation? I was actually just trying to add debug output to the existing script, not trying to modify the script, when I encountered this error.
For now I have just renamed the variable.

Well, in the case that you had no chance to modify the code, e.g. because it is encrypted you could do sth like
int length_original (string s) { return length s }
<<here is the code of your function>>
int length (string s) {return length_original s }

Related

How should I terminate a func in F#

let Trans(DirPath:string) =
if ( numOfVmFiles(DirPath) > 1) then //if there are more than 1 vm files in the directory
Init("")
let VmFiles = ListOfVmFiles(DirPath)
for VmFile in VmFiles do // for each vm file
ReadFile(VmFile)
I got this error:
Error Block following this 'let' is unfinished. Expect an expression.
what should I write?thznk u
The existing answers give you good hints on how to write your code better. You said you are getting an error:
Block following this 'let' is unfinished. Expect an expression.
This typically indicates missing = or wrong indentation after the end of your function (or some easy to miss syntax error like that). In the snippet you posted, all syntax looks good to me, so I suspect there is something wrong elsewhere too. The following gives no errors:
let numOfVmFiles a = 0
let Init a = ()
let ListOfVmFiles a = []
let ReadFile a = ()
let Trans(DirPath:string) =
if ( numOfVmFiles(DirPath) > 1) then
Init("")
let VmFiles = ListOfVmFiles(DirPath)
for VmFile in VmFiles do // for each vm file
ReadFile(VmFile)
You get two warnings - because variable names should be camelCase rather than PascalCase, but no error. As others said, you should probably make Init and ReadFile return something and then you need to collect the results (to make your code more functional), but that's a separate problem.
The problem is that the function does not return a value. Functions must always return a value. If there is nothing to return, return unit. You can return unit as ().
I made some possibly incorrect assumptions here but I tried to make clear what they were. On the trans function I also show how you can specify the return type. It is usually best to let the compiler infer the type until it cannot. Hover over the functions and see what the compiler is telling you about the types. string -> int -> string list means a function takes a string and an int and returns a list of strings.
let init dirName = () //unit is returned... kind of like void but is actually a return value
let listOfVmFiles dirName = ["some";"files"] // list of string
let readFile path = "content of file" //string
let trans(dirPath:string) : string list = // takes a string and returns a list of string represented as string-> string list
let vmFiles = listOfVmFiles(dirPath) // get files from path
if(vmFiles.Length > 1) then init("") // init if more than 1 file
List.map readFile vmFiles // return a list of the content of the files
If a function is performing a side-effect and does not return something then it can be done like so:
let trans(dirPath:string) : unit =
let vmFiles = listOfVmFiles(dirPath)
if(vmFiles.Length > 1) then init("")
List.map readFile vmFiles |> ignore //ignore the result
()
This ignores the result of mapping the readFile function over the list and then returns unit using ().
I recommend fsharp for fun and profit for learning fsharp.
Hope this helps and good luck. Although the syntax seems weird initially stick with it. It's great!
In F# a function returns the value of the last expression it evaluated.
In your particular case it returns unit (), because a for loop returns unit unless its body yields values (in which case you would need to wrap it in a seq).
As mentioned in the comments, this code parses ok- your issue is with an unfinished expression elsewhere in your code.
The rewrite by Devon Buriss is a good example of best practices:
Explicitly declare your function return value in the signature.
ignore function return values if the function is only called for side effects (eg readFile and init("")).
Prefer functional behaviors such as map over imperatives such as for .. do.
As an aside, relying so heavily on side effects is likely to cause you difficulties elsewhere. A more common practice with data crunching is do have a function like readFile return file contents as a seq, and pipe the result to downstream processing:
List.map readFile vmFiles
|> seq.Concat // concatenate the file outputs
|> processContents
Whether or not this is the right thing for you depends on what exactly you intend to do with the contents of each file.

F# Function where given a string and an integer it returns a char at position(integer) from the string

I have a function that returns the char at a location:
let NthChar inpStr indxNum =
if inpStr.Length >=1 then printfn "Character %s" inpStr.[indxNum];
else printfn "Not enough arguments"
Error for
inpStr.Length
and
inpStr.[indxNum]
Error trace:
Lookup on object of indeterminate type based on information prior to this program point. A type annotation may be needed prior to this program point to constrain the type of the object. This may allow the lookup to be resolved.
You're trying to "dot into" something and access it's indexer. Except that when you do this the type of that something is still unknown (maybe it doesn't have an indexer)
So you got that rather explicit error message which also gives you the way to remove it, simply add a type annotation :
// code shortened
let nthChar (inpStr : string) indxNum = inpStr.[indxNum]
// alternative syntax
let nthChar inpStr indxNum = (inpStr : string).[indxNum]

How can I determine if user's input is empty?

I am writing code to generate a JavaCC parser, which will read a user's input and check if it is in any one of a set of languages defined in my code.
One condition on allowable input is that it must not be empty - i.e., the user must enter some block of characters (with length greater than or equal to 1) other than white space " ".
I would like to be able to determine if the user's input is empty, so that an error message can be printed out on the screen in that case.
I have written a production (a.k.a rule) that gets the user's input; it's called Input() and is declared to be void.
In the main method, I have tried to write code which determines if the user's input is empty, by writing:
if parser.Input() == null {
// print error message onto the screen
}
However, I get an error message on the terminal when I try to compile, stating that a 'void' type is not allowed here (I am sure this is referring to Input).
Could I please have a hint/hints for getting around this issue?
Write the Input production like this
boolean Input() : {
} {
<EOF>
{return true;}
|
... // other possibilities here
{return false;}
}
Then, in the main method, you can write
if( parser.Input() ) {
... // report error
}
This solves the problem of reporting the error.
However you may also want to report the language found. For that you could make an enumeration type and have Input return a member of the enumeration. EMPTY could be one of the possibilities.
Language lang = parser.Input() ;
switch( lang ) {
case EMPTY:
... // report error
break ;
case LANGA:
...
break ;
... // etc.
}
Change your type method so this can return a value and you can validate the result, when you do this but change the comparison like this:
if null==parser.Input(){
//print error message on screen
}
Another option is to validate data inside your Input method so you keep it like void.

Lua Error Attempt to perform arithmetic on local variable

Here is the function
calc.lua:
function foo(n)
return n*2
end
Here is my LuaJavaCall
L.getGlobal("foo");
L.pushJavaObject(8);
int retCode=L.pcall(1,1,0); // nResults)//L.pcall(1, 1,-2);
String errstr = L.toString(-1); // Attempt to perform arithmetic on local variable 'n'
Update: as indicated below I needed to use L.pushNumber(8.0) instead of L.pushJavaObject()
Try using L.pushNumber instead of L.pushJavaObject like this:
L.getGlobal("foo");
L.pushNumber(8.0);
int retCode = L.pcall(1,1,0);
String errstr = L.toString(-1);
Lua probably sees JavaObject as a type of 'userdata' in which case there are no predefined operations for it; Lua won't know what to do with a JavaObject * 2 since you didn't define how to handle it.
OTOH, Lua does know how to handle a number since that's a builtin primitive type. For the code snippet you presented, pushing a number would be the least painful way to get it working instead of writing extra code that tells Lua how to work with numbers wrapped inside a JavaObject.

F# strange printfn problem

I was playing around with F# (Visual Studio 2010 beta 1), and I wrote a little console script that asked the user to input 2 numbers and an operator and then executed it.
It works fine, apart from a tiny, but annoying thing: sometimes my printfn instructions are ignored. I placed breakpoints in the code to see that's indeed the case.
The code snippet:
let convert (source : string) =
try System.Int32.Parse(source)
with :? System.FormatException ->
printfn "'%s' is not a number!" source;
waitForExitKey();
exit 1
let read =
printfn "Please enter a number.";
System.Console.ReadLine
let num1 : int = read() |> convert // the printfn in the read function is run...
let num2 : int = read() |> convert // ... but here is ignored
This is not the complete source of course, but I think that'll be enough. If you need the complete source just let me know.
So my question is pretty simple: what causes this issue with printfn? Am I doing something wrong?
Thanks in advance,
ShdNx
This page has a partial explanation of what's going on, but the short and sweet version is that F# will execute any value on declaration if it doesn't take parameters.
let read =
printfn "Please enter a number."
System.Console.ReadLine
Since read doesn't take any parameters, its executed immediately on declaration and binds the return value of the function to the identifier read.
Incidentally, your return value happens to be a function with the type (unit -> string). This results because F# automatically curries functions if they aren't passed all of their parameters. ReadLine expects one unit parameter, but since it isn't passed on, you actually bind read to the ReadLine function itself.
The solution is as follows:
let read() = // read takes one unit parameter
printfn "Please enter a number."
System.Console.ReadLine() // pass paramter to ReadLine method
Since read takes one parameter, its re-evaluated each time its called. Additionally, we're passing a parameter to ReadLine, otherwise we'll just return the ReadLine function as a value.
I understand that this can be confusing. In your example, printfn runs earlier than you think. It will actually execute even without the call to read(), i.e., comment out the last two lines and you will still see a message being printed.
I think your intention is something like this:
let read() =
printfn "Please enter a number.";
System.Console.ReadLine()
This will create a "reusable" function instead of binding a function to an identifier as in your original example.
As a sidenote, the use of semi-colons here is optional so you can just write:
let read() =
printfn "Please enter a number."
System.Console.ReadLine()

Resources