BugLet? Short Circuits

  • Thread starter Thread starter Mike
  • Start date Start date
M

Mike

How come this keyboard loop under VB.NET

while (true)
if Console.KeyAvailable() and (Console.ReadKey(True) = 27) then
exit while
end if
System.Threading.Thread.Sleep(75)
end while

does not work (short circuit) and must be like this:

while (true)
if Console.KeyAvailable() then
if (Console.ReadKey(True) = 27) then
exit while
end if
end if
System.Threading.Thread.Sleep(75)
end while

It seems like the if condition is not utilizing short circuits.

A AND B

if A is false don't bother even looking at B because the end result
is false.

PS: I just found AndALSO. Why? What was it needed? So odd. Was it
to maintain backward compatible VB versions that never supported
common sense logic?

--
 
Mike said:
PS: I just found AndALSO. Why? What was it needed?

What a question! You're looking for something you need. Now that you've
found it you wonder why it's there. Strange... Maybe you really should start
thinking logical, not bitwise - in general.



Armin
 
Michael Williams said:
Nah. It was to make it easy for beginners and first time casual Windows
programmers, the sort of people that VB.Net is specifically aimed at ;-)

http://www.microsoft.com/express/download/

So, what should Microsoft have done? Not adding short-circuit (logical)
operators? Renaming 'And' and 'Or' to 'BitAnd' and 'BitOr'?

It's pretty clear that short-circuit operators were missing in Classic VB;
there has always been a loud demand for these operators.

(BTW, I would have preferred 'BitAnd' and 'BitOr' as bitwise operators, and
'And' and 'Or' as logical operators, but this would have broken compatiblity
completely ;-)).
 
So, what should Microsoft have done? Not adding short-circuit (logical)
operators? Renaming 'And' and 'Or' to 'BitAnd' and 'BitOr'?

It's pretty clear that short-circuit operators were missing in Classic VB;
there has always been a loud demand for these operators.

(BTW, I would have preferred 'BitAnd' and 'BitOr' as bitwise operators, and
'And' and 'Or' as logical operators, but this would have broken compatiblity
completely ;-)).

Thats the way it was pre-beta2.
 
That does not explain why the original code structure did not work:
if Console.KeyAvailable() and (Console.ReadKey(True) = 27) then

Console.KeyAvailable returns a logical true as does (Console.ReadKey(True=27). The bit wise and
operation should still result in a value that should be coerced into true. What am I missing?
 
Mike said:
How come this keyboard loop under VB.NET

while (true)
if Console.KeyAvailable() and (Console.ReadKey(True) = 27) then
exit while
end if
System.Threading.Thread.Sleep(75)
end while

does not work (short circuit) and must be like this:

while (true)
if Console.KeyAvailable() then
if (Console.ReadKey(True) = 27) then
exit while
end if
end if
System.Threading.Thread.Sleep(75)
end while

It seems like the if condition is not utilizing short circuits.

A AND B

if A is false don't bother even looking at B because the end result is
false.

PS: I just found AndALSO. Why? What was it needed? So odd. Was it to
maintain backward compatible VB versions that never supported common sense
logic?


I think your main question has been addressed.

What compiler options and version are you using to get this to compile?

Console.ReadKey(True) = 27 should be invalid comparison of a ConsoleKeyInfo
object and an integer.
 
Family said:
Console.ReadKey(True) = 27 should be invalid comparison of a
ConsoleKeyInfo object and an integer.

Right, it should of been:

Console.ReadKey(True).key

You must of tried it. :)

I have a habit of retyping code from memory and naturally thinking
classes (now the VB.NET is being dressed up like real OOPs) have
default operators. Sorry, I guess I will be one of the few will have
have C++ to VB.NET pains - better off if I didn't know C++ perhaps?

But I guess ConsoleKeyInfo() class does default operators :-)

Again I am not knocking VB.NET, but it is a very common OOPS concepts
especially in the complex world of having lots of methods and
properties - a concern the VB design term has and is addressing, see
the last VB101 Design Meeting video.
 
Mike said:
Right, it should of been:

Console.ReadKey(True).key
You must of tried it. :)

I have a habit of retyping code from memory and naturally thinking classes
(now the VB.NET is being dressed up like real OOPs) have default
operators. Sorry, I guess I will be one of the few will have have C++ to
VB.NET pains - better off if I didn't know C++ perhaps?

But I guess ConsoleKeyInfo() class does default operators :-)

Again I am not knocking VB.NET, but it is a very common OOPS concepts
especially in the complex world of having lots of methods and properties -
a concern the VB design term has and is addressing, see the last VB101
Design Meeting video.


You can compare almost anything in VB. Whether it makes sense is another
story. With "Option Strict On" you are protected from most mistakes.

For clarification, ConsoleKeyInfo is a struct. For the comparison I would
use a ConsoleKey enumeration item. That will make the code more readable.
Actually the code could be written like this: (Forgive me as I don't know
what key 27 is equal).

Dim k As ConsoleKey
While (True)
k = Console.ReadKey(True).Key
If (k = ConsoleKey.Q) Then
Exit While
End If
End While

In other words, you don't even need to check the key available. ReadKey
will block.
 
Family said:
You can compare almost anything in VB. Whether it makes sense is
another story. With "Option Strict On" you are protected from most
mistakes.

For clarification, ConsoleKeyInfo is a struct. For the comparison I
would use a ConsoleKey enumeration item. That will make the code more
readable. Actually the code could be written like this: (Forgive me as
I don't know what key 27 is equal).
Escape

Dim k As ConsoleKey
While (True)
k = Console.ReadKey(True).Key
If (k = ConsoleKey.Q) Then
Exit While
End If
End While

In other words, you don't even need to check the key available. ReadKey
will block.

Well, thats a different need. This is for an threaded application so
the cooperative non-blocking keyboard loop is used under this
considerations. Coupled with the other post regarding threads and
callbacks, the completed example for our SDK was done:

' file: Example-CallBack2.vb
' About: Example of Wildcat Callback

Option Strict On
Option Explicit On

Imports System
Imports System.Threading
Imports System.Runtime.InteropServices
Imports Wildcat.Net.Server

Module Module1

sub BeepStartUp()
Console.Beep(1000, 200) : Console.Beep(2000, 50)
end sub

sub BeepShutDown()
Console.Beep(2000, 200) : Console.Beep(1000, 50)
end sub

Function GetKey() as integer
return console.ReadKey(true).key
end function

Function KeyPressed() as boolean
return Console.KeyAvailable()
end function

Delegate Function cbWildcatDelegate( _
ByVal userdata As Integer, _
ByVal msg As IntPtr) as Long

Function DoCallBack( _
ByVal userdata As Integer, _
ByVal msg As IntPtr) as Long
try
Dim cmsg As TChannelMessage
cmsg.Channel = Marshal.ReadInt32(msg, 0)
cmsg.SenderId = Marshal.ReadInt32(msg, 4)
cmsg.UserData = Marshal.ReadInt16(msg, 8)
cmsg.DataSize = Marshal.ReadInt16(msg, 10)
Console.WriteLine("CB: Ch: {0} sid: {1} ud: {2} ds: {3}", _
cmsg.Channel, _
cmsg.SenderId, _
cmsg.UserData, _
cmsg.DataSize)
Catch ex As Exception
Console.WriteLine("-------------------------------------")
Console.WriteLine("Exception: {0}", ex.Message)
Console.WriteLine("{0}", ex.StackTrace)
Console.WriteLine("-------------------------------------")
end try
return 0
end function

Public Function PrepareCallback( _
ByVal cbproc As cbWildcatDelegate, _
ByVal userdata As Integer) As Boolean
SetupWildcatCallback(cbProc, userdata)
End Function

'-------------------------------------------
' MAIN
'-------------------------------------------

Sub Main()
BeepStartUp()

' Find/Connect to WAN/LAN server
WildcatServerConnect(0)
Console.Writeline("- Connected to: {0}",GetConnectedServer())

' Creates thread
WildcatServerCreateContext()

' adds callback
PrepareCallBack(AddressOf DoCallBack, 0)

' listen to some channels
dim ChatChannel as Integer = OpenChannel("chat.0")
dim SysPageChannel as Integer = OpenChannel("system.page")
dim SysEventChannel as Integer = OpenChannel("system.event")

' cooperative keyboard loop
while (true)
if KeyPressed() AndAlso (GetKey() = 27) then
exit while
end if
Thread.Sleep(75)
end while

WildcatServerDeleteContext()
Console.Writeline("<CLICK>")

BeepShutDown()

End Sub

End Module

--
 
Btw, 27 is Escape key code, so it could be made more readable
consolekey.escape enumerated value:

' cooperative keyboard loop
while (true)
if KeyPressed() AndAlso (GetKey() = ConsoleKey.Escape) then
exit while
end if
Thread.Sleep(75)
end while

If you are wondering why the Sleep(75) is because without, it is an
inefficient loop with a tremendous amount of context switching thus
increasing the CPU of the main thread. A sleep(0) (considered a POKE
concept) is equivalent inefficient.

That said some languages with their own keyboard interface (i.e, .NET
Console interface) may be concurrently cooperative with the main
thread already, in order words it may be using an its Sleep(x) or it
might be using a hidden window with a message loop.

The test is to remove the Sleep(75) and look at Task Manager. If you
see zero CPU for the process, then Console is already optimized for a
keyboard loops.

However, in general, such loops, a Sleep(X) where X at least one
quantum is generally useful.

--
 
Stewart said:
That does not explain why the original code structure did not work:
if Console.KeyAvailable() and (Console.ReadKey(True) = 27) then

Console.KeyAvailable returns a logical true as does (Console.ReadKey(True=27). The bit wise and
operation should still result in a value that should be coerced into true. What am I missing?

Right. I thought maybe the issue was VB Boolean value of -1 was part
of it. So I even explore ideas like using DeMorgan's Theorem:

NOT (A AND B) = (NOT A OR NOT B)
NOT (A OR B) = (NOT A) AND (NOT B)

The Lingo used to help you remember the theorem:

"A NAND is equal to a negated input OR"
"A NOR is equal to a negated input AND"

Its the basics of integrated circuits since all chips are AND gates so
to create an OR gate, the above theorem is used.

I use the theorem a lot to reduce complex conditions.

Nonetheless, but with VB the bottom line is that the compiler does not
produce Short Circuiting OP codes. Thats the bottom line.

It will check the result of all inputs first before it compares.

--
 
Mike said:
Right. I thought maybe the issue was VB Boolean value of -1 was part
of it.

No. Booleans have values of True or False. The actual underlying binary
representation is irrelevant.

Andrew
 
Back
Top