Page 2 of 3

Re: A Walrus :=

Posted: Wed Sep 13, 2023 12:43 pm
by mk-soft
Lord wrote: Wed Sep 13, 2023 7:14 am Please stay BASIC.
There are too many influences from other programming languages lately. :evil:
I am of the same mind

Re: A Walrus :=

Posted: Wed Sep 13, 2023 4:00 pm
by yuki
the.weavster wrote: Wed Sep 13, 2023 9:00 am
yuki wrote: Tue Sep 12, 2023 7:27 pm Though, I might put forward an alternative syntax suggestion:

Code: Select all

If Define result = OpenFile(#PB_Any, filename$)
  ; do work with result
EndIf
If an alternative syntax is considered to be more BASIC that's cool, I'd just like to see that pattern, which is common in PB, compressed.
That's sort of what I was going for: a more BASIC-way, using a keyword in plain English rather than special symbolic operator. (Though, ":=" does harken back fun times dabbling in Delphi, as well as more recently Go).

I actually can't recall any BASIC-likes that support assignment expressions, but I'd be interested to know if/which prior works do exist. (Though, there are so many interpretations of what constitutes a BASIC. Most implementations don't have procedures but instead subroutines. Newer ones, like PB, of course do. Others might add OOP or various other features with debatable merit. It's such a vague categorisation.)

It's probably avoided because there's the potential of making flow and side-effects less obvious:

Code: Select all

; Try and open main or fallback file, and read all text from it.
If (file := ReadFile(#PB_Any, "path") Or file := ReadFile(#PB_Any, "path-fallback")) And (fileText$ := ReadString(file, #PB_File_IgnoreEOL)
  ; File exists and has non-empty text. Do something with it. Maybe parse.
  *something = DoSomethingWithFileContents(fileText$)
Else
  ; File does not exist or is empty. Do some other thing. Maybe create/init defaults.
  *something = DoSomethingWhenMissingFile()
EndIf
Currently, that'd be expressed like so:

Code: Select all

; Try and read from main or fallback locations...
file = ReadFile(#PB_Any, "path")
If Not file
  file = ReadFile(#PB_Any, "path-fallback")
EndIf

; Read file text if we've opened one...
If file
  fileText$ = ReadString(file, #PB_File_IgnoreEOL)
EndIf

; Process contents if any, otherwise create defaults...
If fileText$
  *something = DoSomethingWithFileContents(fileText$)
Else
  *something = DoSomethingWhenMissingFile()
EndIf
And while the current approach might take a second longer to read, it's likely more widely intelligible, so more ... "basic" ? :lol:

Things could get super bizarre with different conditionally defined/assigned variables mixed (perhaps themselves being used in other conditionally assigned variables). Or they could be elegant like the example in OP. This can be said for any code since anything is a footgun in the right hands/feet, and most people would hopefully use it responsibly.

A basic approach might have If Define syntax support only the single assignment being tested for truthyness, and forbid boolean logic or nested defines (no defines-as-expressions). That would greatly simplify implementation as well:
  • If is checked as usual.
  • If Define is checked as "Define " and then If definedVarNameHere.
    • Allows, e.g.:
      • If Define *usr = AllocateStructure(User)
      • If Define file = OpenFile(#PB_Any, "file.txt")
    • Forbids, e.g.:
      • If Define len = Length(str$) > 100
      • If Define file = OpenFile(#PB_Any, "file.txt") And Define fileText$ = ReadString(file, #PB_File_IgnoreEOL)
Though, because of the complexity this adds, I'm pretty torn.

Re: A Walrus :=

Posted: Wed Sep 13, 2023 4:18 pm
by jacdelad
Little John wrote: Wed Sep 13, 2023 12:39 pm
jacdelad wrote: Wed Sep 13, 2023 11:56 am Nobody would be forced to use it...
Well, that depends on your definition of “usage”.
What do you mean? Even with the walrus you can still use = plus an if-clause and avoid it.

Re: A Walrus :=

Posted: Mon Sep 25, 2023 3:13 pm
by Quin
BarryG wrote: Wed Sep 13, 2023 9:59 am
Lord wrote: Wed Sep 13, 2023 7:14 amPlease stay BASIC.
There are too many influences from other programming languages lately. :evil:
100% agreed. I chose PureBasic for BASIC.
PB is one of the furthest BASIC-style languages from actual BASIC, so no idea what you're on about. I've never seen another BASIC language use . for types, for example.
Little John wrote: Wed Sep 13, 2023 12:39 pm
jacdelad wrote: Wed Sep 13, 2023 11:56 am Nobody would be forced to use it...
Well, that depends on your definition of “usage”.
Um...no it doesn't? We're not at all asking for the old syntax to be removed. Even if the docs were updated with this syntax, that still doesn't mean you need it.

Re: A Walrus :=

Posted: Mon Sep 25, 2023 4:14 pm
by plouf
I also agree on "stay BASIC"

Also i see little advantage in this "another language" infuence
Since can be done in parenthesis style etx

Re: A Walrus :=

Posted: Mon Sep 25, 2023 5:35 pm
by the.weavster
Different BASIC variants have their own assortment of assignment operators for various use cases. Some overlap, some don't:
Visual Basic
FreeBASIC
So I don't even understand the reasoning for claiming this particular suggestion is not BASIC enough.

Re: A Walrus :=

Posted: Mon Sep 25, 2023 6:44 pm
by Little John
jacdelad wrote: Wed Sep 13, 2023 4:18 pm
Little John wrote: Wed Sep 13, 2023 12:39 pm
jacdelad wrote: Wed Sep 13, 2023 11:56 am Nobody would be forced to use it...
Well, that depends on your definition of “usage”.
Even with the walrus you can still use = plus an if-clause and avoid it.
As I wrote before, I have nothing at all against the Walrus operator ...

But Im getting headache when I'm reading code like this:

Code: Select all

If Define result = OpenFile(#PB_Any, filename$)
  ; do work with result
EndIf
The following “argument” comes up repeatedly year after year:
Nobody would be forced to use it...
I'm somewhat tired of responding to that, so here is just a short version.
As I wrote, it depends on your definition of “usage”.
True is: Nobody is forced to write it.
However, the problem is about readability. People are exchanging code e.g.here on the forum, aren't they?
So if I want to discuss PureBasic code posted here about a topic I am interested in, then I have to read it. Usage of code does not only include writing, but also reading. And I don't want to get headache when reading PureBasic code.

Re: A Walrus :=

Posted: Mon Sep 25, 2023 11:01 pm
by yuki
Little John wrote: Mon Sep 25, 2023 6:44 pm However, the problem is about readability. People are exchanging code e.g.here on the forum, aren't they?
So if I want to discuss PureBasic code posted here about a topic I am interested in, then I have to read it. Usage of code does not only include writing, but also reading. And I don't want to get headache when reading PureBasic code.
I figured you meant the code-sharing aspect of things, thus taking on the feature from 3rd parties. That's a straightforward, respectable opinion.

This isn't a loaded question – I'm genuinely curious – but how do you feel about other later or divisive PB features? Things like:
  • Modules
  • EnableExplicit
  • #PB_Any vs. Enumeration
  • BindEvent() vs. explicit event-loop handling
  • Macros to some extent (the brain-melting hacky tricks)
I know some of these get more hate than others, but each allow for extremely different styles of programming. As someone who'd be interested in releasing code to the community, I'm very curious what style is most tolerable for the largest number of people.

I actually want to poll this somewhere (as well as OS usage), but save that for another time.

(Also, I sort of envy you not being in a constant state of headache already :lol: )

Re: A Walrus :=

Posted: Mon Sep 25, 2023 11:08 pm
by Kuron
WTF happened to this thread?

Re: A Walrus :=

Posted: Tue Sep 26, 2023 4:54 am
by Quin
Maybe it's the fact that I use a screen reader, but all code gives me the exact same level of headache ;)

Re: A Walrus :=

Posted: Tue Sep 26, 2023 10:34 am
by NicTheQuick
I like the Walrus idea a lot. It's easy to read too. But there is still a problem to be solved. What if you want to compare to something different than just non-zero? How would the syntax look like?
Like so?

Code: Select all

If Not file := OpenFile(#PB_Any, "file.txt")
	MessageRequester("Error", "Can not open file.")
EndIf
Or does it need additional brackets?

Code: Select all

If Not (file := OpenFile(#PB_Any, "file.txt"))
	MessageRequester("Error", "Can not open file.")
EndIf
And what if you want to do a more sophisticated comparison? Is this the way?

Code: Select all

If (length := Len(text)) > 2
	Debug "String too long."
EndIf
And can you reuse the assigned variable in the same condition?

Code: Select all

If (file := CreateFile(#PB_Any, "create_me.txt")) And CloseFile(file)
	Debug "File created."
Else
	Debug "Oh oh."
EndIf
But besides a simple If condition we could use it with other things quite well, for example like this:

Code: Select all

; Without Walrus (option 1)
Repeat
	*element = NextElement(mylist())
	If Not *element
		Break
	EndIf
	; do stuff
ForEver

; Without Walrus (option 2)
*element = NextElement(mylist())
While *element
	; do stuff
	*element = NextElement(mylist())
Wend

; With Walrus
While *element := NextElement(mylist())
	; do stuff
Wend
And yes, I know there is ForEach but consider this code as an example for everything that can be iterated and is not a native datatype.

I really see potential here and I don't think it is that hard to read. Macros are hard to read but not this simple thing.

Re: A Walrus :=

Posted: Tue Sep 26, 2023 5:12 pm
by Little John
NicTheQuick wrote:

Code: Select all

; With Walrus
While *element := NextElement(mylist())
	; do stuff
Wend
That's a good example!

Re: A Walrus :=

Posted: Tue Sep 26, 2023 5:39 pm
by yuki
NicTheQuick wrote: Tue Sep 26, 2023 10:34 am And can you reuse the assigned variable in the same condition?

Code: Select all

If (file := CreateFile(#PB_Any, "create_me.txt")) And CloseFile(file)
	Debug "File created."
Else
	Debug "Oh oh."
EndIf
Watch out: in this case, your program will always "oh oh" :wink:
NicTheQuick wrote: Tue Sep 26, 2023 10:34 am

Code: Select all

While *element := NextElement(mylist())
	; do stuff
Wend
I'm very prone to this pattern.

Often, consuming a data stream requires duplication of the get-next operation (your option 2), or becomes more wordy (your option 1) with an unconditional loop and break condition inside it. Either existing approach is less clear and arguably more prone to bugs because of it.

So walrus (or While Define) syntax would be great.

(another workaround I didn't mention is to design functions specifically around this, setting results through a pointer parameter, and returning either a status code to check or non-zero on success, sort of like ReceiveNetworkData(...). this is good when possible but otherwise requires wrapper functions)

Re: A Walrus :=

Posted: Tue Sep 26, 2023 5:45 pm
by NicTheQuick
yuki wrote: Tue Sep 26, 2023 5:39 pm
NicTheQuick wrote: Tue Sep 26, 2023 10:34 am And can you reuse the assigned variable in the same condition?

Code: Select all

If (file := CreateFile(#PB_Any, "create_me.txt")) And CloseFile(file)
	Debug "File created."
Else
	Debug "Oh oh."
EndIf
Watch out: in this case, your program will always "oh oh" :wink:
Haha, you're right. CloseFile() never returns anything, at least according to the documentation. Well, I think you've understood what I meant with that example. :D

Re: A Walrus :=

Posted: Wed Sep 27, 2023 7:45 am
by the.weavster
NicTheQuick wrote: Tue Sep 26, 2023 10:34 am But besides a simple If condition we could use it with other things quite well
The more versatile the better imo. Just expanding a little on the OpenFile() example:

Code: Select all

If file := OpenFile(#PB_Any,  "file.txt")
	While text.s := ReadString(file)
		; do work with text
	Wend
	CloseFile(file)
EndIf