A Walrus :=

Got an idea for enhancing PureBasic? New command(s) you'd like to see?
User avatar
mk-soft
Always Here
Always Here
Posts: 6209
Joined: Fri May 12, 2006 6:51 pm
Location: Germany

Re: A Walrus :=

Post 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
My Projects ThreadToGUI / OOP-BaseClass / EventDesigner V3
PB v3.30 / v5.75 - OS Mac Mini OSX 10.xx - VM Window Pro / Linux Ubuntu
Downloads on my Webspace / OneDrive
User avatar
yuki
Enthusiast
Enthusiast
Posts: 101
Joined: Sat Mar 31, 2018 9:09 pm

Re: A Walrus :=

Post 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.
Last edited by yuki on Wed Sep 13, 2023 4:36 pm, edited 2 times in total.
User avatar
jacdelad
Addict
Addict
Posts: 1993
Joined: Wed Feb 03, 2021 12:46 pm
Location: Riesa

Re: A Walrus :=

Post 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.
Good morning, that's a nice tnetennba!

PureBasic 6.21/Windows 11 x64/Ryzen 7900X/32GB RAM/3TB SSD
Synology DS1821+/DX517, 130.9TB+50.8TB+2TB SSD
Quin
Addict
Addict
Posts: 1131
Joined: Thu Mar 31, 2022 7:03 pm
Location: Colorado, United States
Contact:

Re: A Walrus :=

Post 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.
plouf
Enthusiast
Enthusiast
Posts: 281
Joined: Fri Apr 25, 2003 6:35 pm
Location: Athens,Greece

Re: A Walrus :=

Post 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
Christos
User avatar
the.weavster
Addict
Addict
Posts: 1576
Joined: Thu Jul 03, 2003 6:53 pm
Location: England

Re: A Walrus :=

Post 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.
Little John
Addict
Addict
Posts: 4779
Joined: Thu Jun 07, 2007 3:25 pm
Location: Berlin, Germany

Re: A Walrus :=

Post 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.
User avatar
yuki
Enthusiast
Enthusiast
Posts: 101
Joined: Sat Mar 31, 2018 9:09 pm

Re: A Walrus :=

Post 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: )
User avatar
Kuron
Addict
Addict
Posts: 1626
Joined: Sat Oct 17, 2009 10:51 pm
Location: Pacific Northwest

Re: A Walrus :=

Post by Kuron »

WTF happened to this thread?
Best wishes to the PB community. Thank you for the memories. ♥️
Quin
Addict
Addict
Posts: 1131
Joined: Thu Mar 31, 2022 7:03 pm
Location: Colorado, United States
Contact:

Re: A Walrus :=

Post by Quin »

Maybe it's the fact that I use a screen reader, but all code gives me the exact same level of headache ;)
User avatar
NicTheQuick
Addict
Addict
Posts: 1504
Joined: Sun Jun 22, 2003 7:43 pm
Location: Germany, Saarbrücken
Contact:

Re: A Walrus :=

Post 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.
Last edited by NicTheQuick on Tue Sep 26, 2023 5:23 pm, edited 1 time in total.
The english grammar is freeware, you can use it freely - But it's not Open Source, i.e. you can not change it or publish it in altered way.
Little John
Addict
Addict
Posts: 4779
Joined: Thu Jun 07, 2007 3:25 pm
Location: Berlin, Germany

Re: A Walrus :=

Post by Little John »

NicTheQuick wrote:

Code: Select all

; With Walrus
While *element := NextElement(mylist())
	; do stuff
Wend
That's a good example!
User avatar
yuki
Enthusiast
Enthusiast
Posts: 101
Joined: Sat Mar 31, 2018 9:09 pm

Re: A Walrus :=

Post 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)
Last edited by yuki on Tue Sep 26, 2023 5:52 pm, edited 1 time in total.
User avatar
NicTheQuick
Addict
Addict
Posts: 1504
Joined: Sun Jun 22, 2003 7:43 pm
Location: Germany, Saarbrücken
Contact:

Re: A Walrus :=

Post 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
The english grammar is freeware, you can use it freely - But it's not Open Source, i.e. you can not change it or publish it in altered way.
User avatar
the.weavster
Addict
Addict
Posts: 1576
Joined: Thu Jul 03, 2003 6:53 pm
Location: England

Re: A Walrus :=

Post 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
Post Reply