Io Language: Exception: Sequence does not respond to 'openForReading' - iolanguage

I'm study "seven languages in seven weeks".
On Io charpter, I run following example failed with following exception.
#phonebook.io
OperatorTable addAssignOperator(":", "atPutNumber")
curlyBrackets := method(
r := Map clone
call message arguments foreach(arg,
r doMessage(arg)
)
r
)
Map atPutNumber := method(
self atPut(
call evalArgAt(0) asMutable removePrefix("\"") removeSuffix("\""),
call evalArgAt(1))
)
s := File with("phonebook.txt" openForReading contents)
phoneNumbers := doString(s)
phoneNumbers keys println
phoneNumbers values println
phonebook.txt
{
"Bob Smith" : "12345",
"Mary Walsh" : "5678"
}
Exception message:
Exception: Sequence does not respond to 'openForReading' ---------
Sequence openForReading phonebook.io 16 File with
phonebook.io 16 CLI doFile Z_CLI.io 140
CLI run IoState_runCLI() 1
phonebook.io and phonebook.txt in same folder.

Compare code line by line, following line
s := File with("phonebook.txt" openForReading contents)
should correct as:
s := File with("phonebook.txt") openForReading contents
At last works as expected:
$> io phonebook.io
list(Mary Walsh, Bob Smith)
list(5678, 12345)

Related

Updating my current script which modifies multiple lines into a single one

My current script copies text like this with a shortcut:
:WiltedFlower: aetheryxflower ─ 4
:Alcohol: alcohol ─ 3,709
:Ant: ant ─ 11,924
:Apple: apple ─ 15
:ArmpitHair: armpithair ─ 2
and pastes it modified into a single line
Pls trade 4 aetheryxflower 3 alcohol 11 ant 15 apple 2 armpithair <#id>
As you can see there are already two little problems, the first one is that it copies only the number/s before a comma if one existed instead of ignoring it. The second is that I always need to also copy before hitting the hotkey and start re/start the script, I've thought of modifying the script so that it uses the already selected text instead of the copied one so that I can bind it with a single hotkey.
That is my current script, it would be cool if anyone can also tell me what they used and why exactly, so that I also get better with ahk
!q::
list =
While pos := RegExMatch(Clipboard, "(\w*) ─ (\d*)", m, pos ? pos + StrLen(m) : 1)
list .= m2 " " m1 " "
Clipboard := "", Clipboard := "Pls trade " list " <#951737931159187457>"
ClipWait, 0
If ErrorLevel
MsgBox, 48, Error, An error occurred while waiting for the clipboard.
return
If the pattern of your copied text dont change, you can use something like this:
#Persistent
OnClipboardChange:
list =
a := StrSplit(StrReplace(Clipboard, "`r"), "`n")
Loop,% a.Count() {
b := StrSplit( a[A_Index], ": " )
c := StrSplit( b[2], " - " )
list .= Trim( c[2] ) " " Trim( c[1] ) " "
}
Clipboard := "Pls trade " list " <#951737931159187457>"]
ToolTip % Clipboard ; just for debug
return
With your example text, the output will be:
Pls trade aetheryxflower ─ 4 alcohol ─ 3,709 ant ─ 11,924 apple ─ 15 armpithair ─ 2 <#951737931159187457>
And this will run EVERY TIME your clipboard changes, to avoid this, you can add at the top of the script #IfWinActive, WinTitle or #IfWinExist, WinTitle depending of your need.
The answer given would solve the problem, assuming that it never changes pattern as Diesson mentions.
I did the explanation of the code you provided with comments in the code below:
!q::
list = ; initalize a blank variable
; regexMatch(Haystack, regexNeedle, OutputVar, startPos)
; just for frame of reference in explanation of regexMatch
While ; loop while 'pos' <> 0
pos := RegExMatch(Clipboard ; Haystack is the string to be searched,
in this case the Clipboard
, "(\w*) ─ (\d*)" ; regex needle in this case "capture word characters
(a-z OR A-Z OR 0-9 OR _) any number of times, space dash space
then capture any number of digits (0-9)"
, m ; output var array base name, ie first capture will be in m1
second m2 and so on.
, pos ? pos + StrLen(m) : 1) ; starting position for search
"? :"used in this way is called a ternary operator, what is saying
is "if pos<>0 then length of string+pos is start position, otherwise
start at 1". Based on the docs, this shouldn't actually work well
since 'm' in this case should be left blank
list .= m2 " " m1 " " ; append the results to the 'list' variable
followed with a space
Clipboard := "" ; clear the clipboard.
Clipboard := "Pls trade " list " <#951737931159187457>"
ClipWait, 0 ; wait zero seconds for the clipboard to change
If ErrorLevel ; if waiting zero seconds for the clipboard to change
doesn't work, give error msg to user.
MsgBox, 48, Error, An error occurred while waiting for the clipboard.
return
Frankly this code is what I would call quick and dirty, and seems unlikely to work well all the time.

RESTRequest.Execute error - No mapping for the Unicode character exists in the target multi-byte code page

I'm using Delphi 10.4 (with patches 1, 2 and 3) on Windows 10 64bit to build a VCL Web Client application.
I have an API running on RAD Server, and I can get information from it using the below VCL Webclient application with no trouble. However, when I try to insert data into the API resources through a POST method, I got the following error message from the TRESRequest.Execute() method call:
No mapping for the Unicode character exists in the target multi-byte code page
Though I got this error message, the JSON data is being sent to the API and is saved to the database correctly. It seems that at a certain point of the Execute() method, an error is generated after the data has been sent to the server.
I've already tried TEncoding.UTF8.GetBytes(), TEncoding.ASCII.GetBytes(), and Unicode, without success.
This is my code:
procedure TForm1.BTPostClick(Sender: TObject);
var
strjson : string;
jo : TJSONObject;
begin
strjson :=
'{' +
'"CUST_ID": 1500,' +
'"CUST_NAME": "John Doe Max",' +
'"CUST_COUNTERTOTAL": "500",' +
'"CUST_DETAILS": "This is just a test"' +
'}';
// jo := TJSONObject.ParseJSONValue(TEncoding.Unicode.GetBytes(StrJson),0) as TJSONObject;
// jo := TJSONObject.ParseJSONValue(TEncoding.ASCII.GetBytes(StrJson),0) as TJSONObject;
jo := TJSONObject.ParseJSONValue(TEncoding.UTF8.GetBytes(StrJson),0) as TJSONObject;
Memo1.Clear;
Memo1.Lines.Add(jo.ToString);
RestRequest1.ClearBody;
RestRequest1.Method := rmPost;
RestResponse1.ResetToDefaults;
RestRequest1.AddBody(jo);
RestRequest1.Execute; // ==> error: No mapping for the Unicode character exists in the target multi-byte code page
end;
SERVER SIDE code:
procedure TMytestResource1.MytestPost(const AContext: TEndpointContext; const ARequest: TEndpointRequest; const AResponse: TEndpointResponse);
var
s : string;
i : integer;
jo : TJSONObject;
begin
jo := TJSONObject.Create;
jo.AddPair('Response Line 1','Apple is maçã');
jo.AddPair('Response Line 2','Foot is pé ');
jo.AddPair('Response Line 3','There is lá');
jo.AddPair('Exceção Line 3',TJsonString.Create('Exception is exceção'));
//s := jo.ToString; at this point the characters has accents
AResponse.Body.SetValue(jo, True);
end;
Configuration of REST components is as follows :
RestClient1.Accept := 'application/json, text/plain; q=0.9, text/html;q=0.8,';
RestClient1.AcceptCharset := 'utf-8;q=0.8';
RestClient1.AcceptEnconding := 'utf-8';
RestClient1.FallbackCharsetEncoding := 'utf-8';
RestClient1.ContentType := 'application/json'
RestRequest1.Accept := 'application/json, text/plain; q=0.9, text/html;q=0.8,'
RestRequest1.AcceptCharset := 'utf-8;q=0.8';
RestResponse1.ContentEncoding := '';
RestResponse1.ContentType := '';
New Server Side Code (worked fine):
procedure TMytestResource1.CadastraUser(const AContext: TEndpointContext; const ARequest: TEndpointRequest; const AResponse: TEndpointResponse);
var
s : string;
i : integer;
jo : TJSONObject;
Strm : TStringStream;
begin
jo := TJSONObject.Create;
jo.AddPair('Response Line 1','Apple is maçã');
jo.AddPair('Response Line 2','Foot is pé');
jo.AddPair('Response Line 3','There is lá');
jo.AddPair('Response Line 4','Useful is útil');
//AResponse.Headers.SetValue('Content-Type', 'application/json; charset=utf-8'); ==> This line does not make any effect on response
try
// Strm := TStringStream(jo.ToJSON, TEncoding.UTF8); ==> does not work.
Strm := TStringStream.Create(jo.ToJSON, TEncoding.UTF8);
// AResponse.Body.SetStream(Strm, 'application/json; charset=utf-8', true); ==> This line causes an error on VCL WebClient during RestRequest.Execute() method , error is "Invalid enconding name."
AResponse.Body.SetStream(Strm, 'application/json', true); // this works fine.
finally
jo.Free;
end;
end;
So now, new questions arise :
Why does this same program work fine in Delphi 10.3.1 Tokyo under Windows 7, but now in Delphi 10.4 Sydney (patches 1,2,3) on Windows 10 it requires UTF-8 encoding? Is it a Delphi 10.4 issue? Is it a Windows 10 issue?
In my original server side code, I have many Endpoints sending responses using the command AResponse.Body.SetValue(myJSONObject, True); Should I replace all of them by the two new commands?
Strm := TStringStream.Create(jo.ToJSON, TEncoding.UTF8);
AResponse.Body.SetStream(Strm, 'application/json', true);
Code of REST.Client unit where the error is occuring :
Procedure TCustomRestRequest.Execute
...
if LMimeKind <> TMimeTypes.TKind.Binary then
begin
LEncoding := TEncoding.GetEncoding(FClient.FallbackCharsetEncoding); //==> This line is returning nil, though FClient.FallbackCharsetEncoding is filled with 'utf-8'
LContentIsString := True;
end;
end
else
begin
// Even if no fallback, handle some obvious string types
if LMimeKind = TMimeTypes.TKind.Text then
LContentIsString := True;
end;
end;
if LContentIsString then
LContent := FClient.HTTPClient.Response.ContentAsString(LEncoding); // ==> this line is generating the error
finally
LEncoding.Free;
end;
...

Class and methods to trim string not even starting

I am trying to create a class with string trimming functions:
Object subclass: Trimmer [
trimleading: str [ |ch ret|
ch := (str first: 1). "get first character"
ret := str. "make a copy of sent string"
[ch = ' '] whileTrue: [ "while first char is space"
ret := (ret copyFrom: 2). "copy from 2nd char"
ch := ret first: 1. "again test first char"
].
^ret "return value is modified string"
].
trim: str [ |ret|
ret := str.
ret := (trimleading value: ret). "trim leading spaces"
ret := (trimleading value: (ret reverse)). "reverse string and repeat trim leading"
^(ret reverse) "return reverse string"
]
].
oristr := ' this is a test '
('ORI..>>',oristr,'<<') displayNl.
('FINAL>>',((Trimmer new) trim: oristr),'<<') displayNl.
However, it is not running and giving following error:
$ gst trimstring_class.st
trimstring_class.st:10: invalid class body element
trimstring_class.st:17: expected expression
Where is the problem and how can this be solved?
If I remove the . after trimleading method block, as in following code:
Object subclass: Trimmer [
trimleading: str [ |ch ret flag|
ret := str. "make a copy of sent string"
flag := true.
[flag] whileTrue: [ "while first char is space"
ch := ret first: 1. "again test first char"
ch = ' '
ifTrue: [ ret := (ret copyFrom: 2 to: ret size)] "copy from 2nd char"
ifFalse: [flag := false]
].
^ret "value is modified string"
] "<<<<<<< PERIOD/DOT REMOVED FROM HERE."
trim: str [ |ret|
ret := str.
ret := (trimleading value: ret). "trim leading spaces"
ret := (trimleading value: (ret reverse)). "reverse string and repeat trim leading"
^(ret reverse) "return reverse string"
]
].
Then the code starts to run but stops with following error:
$ gst trimstring_class.st
trimstring_class.st:15: undefined variable trimleading referenced
ORI..>> this is a test <<
Object: Trimmer new "<0x7f1c787b4750>" error: did not understand #trim:
MessageNotUnderstood(Exception)>>signal (ExcHandling.st:254)
Trimmer(Object)>>doesNotUnderstand: #trim: (SysExcept.st:1448)
UndefinedObject>>executeStatements (trimstring_class.st:23)
Why trimleading method is undefined now and why gnu-smalltalk did not understand #trim:?
Usually it is wise for a such common use case to check if such functionallity was already implemented. You can take an inspiration from it for your code (you will improve as Smalltalk programmer too). Take a look at trimBlanksFrom: from sports.st:
SpStringUtilities class >> trimBlanksFrom: aString [
"^a String
I return a copy of aString with all leading and trailing blanks removed."
<category: 'services'>
| first last |
first := 1.
last := aString size.
[last > 0 and: [(aString at: last) isSeparator]]
whileTrue: [last := last - 1].
^last == 0
ifTrue: [String new]
ifFalse: [
[first < last and: [(aString at: first) isSeparator]]
whileTrue: [first := first + 1].
aString copyFrom: first to: last
]
]
If you want to trim only leading spaces you can just take the second part, where it is trimming the leading spaces.
EDIT The OP own code a fixes applied:
Object subclass: Trimmer [
trimleading: str [ |ch ret flag|
ret := str. "make a copy of sent string"
flag := true.
[flag] whileTrue: [ "while first char is space"
ch := ret first: 1. "again test first char"
ch = ' '
ifTrue: [ ret := (ret copyFrom: 2 to: ret size) ] "copy from 2nd char"
ifFalse: [flag := false ]
].
^ret "value is modified string"
] "<<<<<<< PERIOD/DOT REMOVED FROM HERE."
trim: str [ |ret|
ret := str.
ret := self trimleading: (ret copy). "trim leading spaces"
ret := self trimleading: (ret copy reverse). "reverse string and repeat trim leading"
^ (ret reverse) "return reverse string"
]
].
oristr := ' this is a test '
('ORI..>>',oristr,'<<') displayNl.
('FINAL>>',((Trimmer new) trim: oristr),'<<') displayNl.
The were some mistakes that needed to be fixed. If you want to address a selector #trimleading: you have to use self keyword which searches the local class (for own classes or inherited). Next you should not change a variable that you are assigning to you should use a #copy otherwise strange result can be expected.

erlang macro expansion bug

macro module:
-module(macro).
-include_lib("eunit/include/eunit.hrl").
-define(EXPAND(_T), ??_T).
macro_test() ->
?assertEqual("Test", ?EXPAND(Test)),
?assertEqual("Test.test", ?EXPAND(Test.test)).
Is resulting :
6> c(macro).
{ok,macro}
7> eunit:test(macro).
macro: macro_test (module 'macro')...*failed*
in function macro:'-macro_test/0-fun-1-'/1 (macro.erl, line 9)
**error:{assertEqual_failed,[{module,macro},
{line,9},
{expression,"? EXPAND ( Test . test )"},
{expected,"Test.test"},
{value,"Test . test"}]}
=======================================================
Failed: 1. Skipped: 0. Passed: 0.
error
Am I doing something wrong or is this a known bug?
TIA
You're incorrectly assuming that the Erlang compiler treats Test.test as a single token. If you pass the -P option to erlc and examine the output, you'll see that the preprocessor breaks it into multiple tokens. Here's the interesting part of macro.P produced by erlc -P macro.erl:
macro_test() ->
begin
fun(__X) ->
case "Test" of
__X ->
ok;
__V ->
error({assertEqual,
[{module,macro},
{line,8},
{expression,"? EXPAND ( Test )"},
{expected,__X},
{value,__V}]})
end
end("Test")
end,
begin
fun(__X) ->
case "Test . test" of
__X ->
ok;
__V ->
error({assertEqual,
[{module,macro},
{line,9},
{expression,"? EXPAND ( Test . test )"},
{expected,__X},
{value,__V}]})
end
end("Test.test")
end.

Last rune of golang unicode/norm iterator not being read

I'm using the golang.org/x/text/unicode/norm package to iterate over runes in a []byte. I've chosen this approach as I need to inspect each rune and maintain information about the sequence of runes. The last call to iter.Next() does not read the last rune. It gives 0 bytes read on the last rune.
Here is the code:
package main
import (
"fmt"
"unicode/utf8"
"golang.org/x/text/unicode/norm"
)
func main() {
var (
n int
r rune
it norm.Iter
out []byte
)
in := []byte(`test`)
fmt.Printf("%s\n", in)
fmt.Println(in)
it.Init(norm.NFD, in)
for !it.Done() {
ruf := it.Next()
r, n = utf8.DecodeRune(ruf)
fmt.Printf("bytes read: %d. val: %q\n", n, r)
buf := make([]byte, utf8.RuneLen(r))
utf8.EncodeRune(buf, r)
out = norm.NFC.Append(out, buf...)
}
fmt.Printf("%s\n", out)
fmt.Println(out)
}
This produces the following output:
test
[116 101 115 116]
bytes read: 1. val: 't'
bytes read: 1. val: 'e'
bytes read: 1. val: 's'
bytes read: 0. val: '�'
tes�
[116 101 115 239 191 189]
It is possible this is a bug in golang.org/x/text/unicode/norm and its Init() function.
In the package's test and example that I see all use InitString. So as a workaround, if you change:
it.Init(norm.NFD, in)
to:
it.InitString(norm.NFD, `test`)
things will work as expected.
I would suggest opening up a bug report, but beware that since this is in the "/x" directory that package is considered experimental by go developers.
(BTW, I used my the go debugger to help me track down what's going on, but I should say its use was far the kind of debugger I'd like to see.)