Page 250 of 250

Re: Coding: Fleeting Thoughts

Posted: Fri May 03, 2019 3:39 pm UTC
by Flumble
Make some kind of ziplist iterator that provides immutable references to all previous and next items while providing a mutable reference to the current item. :D

Would it make sense to map over the collection producing a collection of Option<Mesh> objects (Some if a mesh is generated) and then zip the two collections? Or can the (re)generation of one mesh depend on the (re)generation of another mesh during the same iteration?

Re: Coding: Fleeting Thoughts

Posted: Fri May 03, 2019 10:00 pm UTC
by Tub
Flumble wrote:Would it make sense to map over the collection producing a collection of Option<Mesh> objects (Some if a mesh is generated) and then zip the two collections? Or can the (re)generation of one mesh depend on the (re)generation of another mesh during the same iteration?

Yeah, I can push all the changes to a separate collection, then merge the changes back into the original collection as a separate pass. That's what I implemented for now. It's cheap compared to the mesh generation, but it's still pointless overhead just to appease the compiler.

I was promised readable idiomatic code with zero-costs abstractions, and now I need to sacrifice both readability and performance just to make it compile. Not sure how I feel about that.

Next step is to implement the actual Octree in Rust. Let's see how pretty the solution for a recursive data structure ends up. I'm anticipating more pain because each object must be both in a HashMap (based on id) and in the Octree (based on location), and although I can guarantee that to be safe, I'm afraid the compiler won't believe me unless I accept the overhead of ref-counting smart pointers.

Re: Coding: Fleeting Thoughts

Posted: Sat May 04, 2019 9:00 pm UTC
by Tub
Update: I ended up solving the mutability problem by using std::Cell. Cells cheat the whole lifetime issue by disallowing getting a reference to the things inside. You can just copy values in, or copy the current value out. With those semantics, it's safe for them to allow changing the value inside without having a mutable reference to them! Now I can do the whole iteration and regeneration on immutable objects, but still clear the dirty-bit inside a Cell<bool>. Won't solve all of my problems, but for this specific problem the borrow checker is happy.

Octree went well. I needed a bit more boilerplate to specify the type of child pointers (either nullptr, pointing to another node, or pointing to a leaf with objects), but thanks to enums that was a lot less code than other statically typed languages would have required.
For now the octree leaves just store the object ids instead of references to the objects, neatly avoiding all the borrowing issues. That's another HashMap lookup per visible object per frame, but those lookups are cheaper than drawing the object, so I guess it's fine. Still irks me, but it's fine.

The previous javascript implementation used a Heap, added all the visible objects by distance, then continued to draw them front-to-back. In rust, I ended up implementing this as a lazy iterator, allowing me to consume items before the Heap is completely filled. Not sure if that's actually faster, but it was a fun challenge.
The Iterator required a ton of boilerplate for all the types, their trait implementations and everything (the BinaryHeap requires 4 traits on its entries just to specify sort order!), but the iterator was really straightforward. Pop the closest item from the queue; if it's an Octree node add all the children to the queue (frustum culled), if it's an Object return it. Match expressions really shine here.

It's also fast. Counting the time between starting the game and watching the last object pop in, the wasm implementation appears to be ~20-50% faster. Success.

Now for the difficult part: not losing interest in the project after finishing the proof-of-concept. :roll:

Re: Coding: Fleeting Thoughts

Posted: Tue May 07, 2019 12:12 pm UTC
by Flumble
Can I get a smartphone (android/ios) to keep javascript and location services active while the screen is off? I'd like to track my (and friends') running and send it to a server in realtime, preferably from a webpage (stores are expensive and sideloading is hard) and without having the phone in drainage mode.

Most of what I found so far are stackoverflow questions of 5+ years ago.


Tub wrote:Now for the difficult part: not losing interest in the project after finishing the proof-of-concept. :roll:

The goal is the proof-of-concept, right? :mrgreen:

Re: Coding: Fleeting Thoughts

Posted: Tue May 07, 2019 3:09 pm UTC
by Xanthir
Flumble wrote:
Can I get a smartphone (android/ios) to keep javascript and location services active while the screen is off? I'd like to track my (and friends') running and send it to a server in realtime, preferably from a webpage (stores are expensive and sideloading is hard) and without having the phone in drainage mode.

Most of what I found so far are stackoverflow questions of 5+ years ago.

No, you can't. It's a sensitive operation that we're not willing to allow a page to push into a background Service Worker and invisibly track you with; the page needs to be open and active to receive location data.

Native apps are just security/privacy nightmares.

Re: Coding: Fleeting Thoughts

Posted: Tue May 07, 2019 10:28 pm UTC
by Flumble
Xanthir wrote:No, you can't. It's a sensitive operation that we're not willing to allow a page to push into a background Service Worker and invisibly track you with; the page needs to be open and active to receive location data.

You standards people always ruin everything!!1! First you can't just retrieve a precise location without the user's permission, now you can't even track people whenever you like! :roll:

I guess I'll go with "keep your phone unlocked constantly" for now. The reason I want to send the position in real time in the first place, is so you can see each other on the map in real time, for which you'll need the screen turned on anyway. (Telling the relative distance would be neat too, but with that much overengineering I may as well put in the effort of turning it into a native program that can access the location in the background.)

Re: Coding: Fleeting Thoughts

Posted: Wed May 08, 2019 3:42 am UTC
by Xeio
I can't decide if this is beautiful or horrifying:

Code: Select all

private static string GetFullName(ClassDeclarationSyntax @class)
{
    string fullName = @class.Identifier.ValueText;
    SyntaxNode node = @class;
    while(true)
    {
        switch (node.Parent)
        {
            case NamespaceDeclarationSyntax @namespace:
                fullName = $"{@namespace.Name}.{fullName}";
                break;
            case ClassDeclarationSyntax outerClass:
                fullName = $"{outerClass.Identifier.ValueText}.{fullName}";
                break;
            default:
                return fullName;
        }
        node = node.Parent;
    }
}

Re: Coding: Fleeting Thoughts

Posted: Thu May 09, 2019 3:29 pm UTC
by Tub
TIL that google will happily store and monetize all of your location data, but considers it a privacy problem when someone else does. :roll:

Xeio wrote:I can't decide if this is beautiful or horrifying:

It can be used for good or evil. I wonder, which is it?

Re: Coding: Fleeting Thoughts

Posted: Sat May 18, 2019 10:00 pm UTC
by Tub
Tub wrote:It's also fast. Counting the time between starting the game and watching the last object pop in, the wasm implementation appears to be ~20-50% faster. Success.

I wasn't happy with this. A bit of benchmarking later, the mesh generation code has been improved by another +120% on top of the previous improvements.

I wouldn't know how to do these kinds of optimizations in a high level language (like JS) when targeting an unknown and changing environment (like a browser).

So my thoughts of the day are:
  • If you need speed, and you're willing to invest the time, wasm works.
  • Hash maps are at the core of most dynamic languages, used to implement objects. Lookups are O(1) and presumed to be really fast. However, when you're doing ~150.000 of them per frame, it helps to bring that number down, and it also helps to use a faster (but less secure) hashing function than the default one.

Re: Coding: Fleeting Thoughts

Posted: Mon May 27, 2019 4:48 pm UTC
by Flumble

Code: Select all

const /*or let or var*/ variable = someFunctionOf(variable)

The javascript complaineth. I am sad. Though recursive binding is allowed for the "old" function syntax:

Code: Select all

function variable() {
  return someFunctionOf(variable)
}

Sure, let v=v+5 would make a mess, but in my case someFunctionOf behaves perfectly fine (e.g. (_)=>0) ...if javascript would create a(n undefined) reference for variable first and afterwards replace it with the result of the expression. Changing a reference externally is not weird un-javascript behaviour at all. :roll:

So when can we expect a letrec keyword in ecmascript?

Re: Coding: Fleeting Thoughts

Posted: Tue May 28, 2019 12:31 am UTC
by hotaru
Flumble wrote:Though recursive binding is allowed for the "old" function syntax:

Code: Select all

function variable() {
  return someFunctionOf(variable)
}


the equivalent of that code with const does work, though:

Code: Select all

const variable = () => someFunctionOf(variable);

Re: Coding: Fleeting Thoughts

Posted: Tue May 28, 2019 6:04 am UTC
by phlip
it can be interesting to see which dynamic languages let you do this, and which ones don't...

Code: Select all

phlip@boris:~$ python
Python 3.6.7 (default, Oct 22 2018, 11:32:17)
[GCC 8.2.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> a = str(a)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'a' is not defined

phlip@boris:~$ irb
irb(main):001:0> a = a.to_s
=> ""

phlip@charlemagne:~$ js
> var a = '' + a;
> a
'undefined'
> let b = '' + b;
ReferenceError: b is not defined
> const c = '' + c;
ReferenceError: c is not defined

Re: Coding: Fleeting Thoughts

Posted: Tue May 28, 2019 9:07 am UTC
by Tub
Flumble wrote:

Code: Select all

const /*or let or var*/ variable = someFunctionOf(variable)

This works does not explode with var. Anything declared with var has a scope of the whole function, being initialized to undefined before its first assignment. It doesn't work with const or let because of their restricted scope and temporal dead zones.

Flumble wrote:

Code: Select all

function variable() {
  return someFunctionOf(variable)
}

function declarations also have function-level scope; you can reference them before, after, and even during declaration.

However, temporal dead zones still apply for captured variables:

Code: Select all

  let foo2 = foo; // referencing works fine
  foo(); // calling it would access x early; this throws.
  let x = 42;
  function foo() {
    return x;
  }
  foo(); // now it works


Flumble wrote:So when can we expect a letrec keyword in ecmascript?

Step #1 would be to show some kind of problem that's easier to solve with the keyword than without. Considering that it works with var, I doubt you'll find one.

Otherwise, Babel is a pretty sweet project. Adding a plugin to implement your favourite code transformation isn't hard.

phlip wrote:it can be interesting to see which dynamic languages let you do this, and which ones don't...

Code: Select all

 ~> php -r '$a = gettype($a); echo $a;'
PHP Notice:  Undefined variable: a in Command line code on line 1
NULL

Depending on your settings (and PHP version), it may output a notice, but otherwise continues as if the variable was NULL.

Re: Coding: Fleeting Thoughts

Posted: Tue May 28, 2019 9:11 am UTC
by chridd
perl:

Code: Select all

$ perl -e 'my $x = $x.""; print $x;'
(no output)
...but...

Code: Select all

$ perl -e 'use strict; my $x = $x.""; print $x'
Global symbol "$x" requires explicit package name at -e line 1.
Execution of -e aborted due to compilation errors.
...so at least Perl treats $x in that statement as referring to a global variable in an outer scope.

Also, on my browser, your JavaScript examples give "ReferenceError: can't access lexical declaration `b' before initialization". And

Code: Select all

const d = function() {return d;};
works.

Also, function statements execute before any other statements, so you can call a function before it's defined.

Re: Coding: Fleeting Thoughts

Posted: Wed May 29, 2019 10:45 am UTC
by Tub
I just realized that javascript's Function class has a unique property. All constructors are functions, so they inherit from Function. This includes the Function constructor:

>> Function instanceof Function
true

A small challenge is thus: create a new variable A (with A !== Function) such that
>> A instanceof A === true

This is also possible in PHP, but requires a different approach. I don't know about python or perl. Not sure if Java or C# and their Reflection APIs allow something to be both a variable and a type.

Re: Coding: Fleeting Thoughts

Posted: Wed May 29, 2019 4:35 pm UTC
by Flumble
hotaru wrote:the equivalent of that code with const does work, though:

Oof, that was a blunder. :oops: Yes, very true. (And in both these cases getting something out of variable would require evaluating the function again and again, which would defeat my usecase) Perhaps I've seen too much haskell in the past weeks, forgetting what eager evaluation looks like.

phlip wrote:it can be interesting to see which [...] languages let you do this, and which ones don't...

I'd recommend using an object/list/dictionary to give the language a bit of leeway. Who knows, maybe there's a language that implicitly stores a reference:

Code: Select all

$ python3 -c "a = {'key': a}"
Traceback (most recent call last):
  File "<string>", line 1, in <module>
NameError: name 'a' is not defined

$ echo 'a={"key" => a}' | irb2.5
Switch to inspect mode.
a={"key" => a}
{"key"=>nil}

$ js -p 'var a = {"key": a}; a'
{ key: undefined }

$ perl5.26.1 -e 'use Data::Dumper; my %a=("key"=>%a); print Dumper \%a'
$VAR1 = {
          'key' => undef
        };

$ javac Main.java
Main.java:4: error: self-reference in initializer
   static final Map<String,Object> map = Map.of("key",(Object)map);
                                                              ^

//this is cheating, really
$ printf '#include<iostream>\n#include<map>\n typedef const std::map<std::string,const void*> Map; int main() { Map map = {{"key", &map}}; std::cout << ((Map*)map.at("key"))->begin()->first << std::endl; return 0; }' | g++ -Wall -Wextra -x c++ -
//no errors

$ php7 -r '$a = array("key"=>$a); echo gettype($a["key"])."\n";'
NULL
//could also cheat with '$a = array("key"=>a); echo gettype(${$a["key"]});'

$ ghc -e 'let a = "value":a in print a'
["value","value","value","value","value","value","value","value","value","value","value","valu^C

(By the way, java doesn't even allow a = () -> a.)
Lisp and friends do have recursive bindings (it's what letrec was born to do), but I guess no language on the imperative side can do it.

Tub wrote:A small challenge is thus: create a new variable A (with A !== Function) such that
>> A instanceof A === true

Is it going to involve defineProperty hacks?
Spoiler:
Oh, I missed one trivial case A=Object

Re: Coding: Fleeting Thoughts

Posted: Wed May 29, 2019 7:29 pm UTC
by Tub
Oh. I missed that rather trivial solution, too. It's true, this will also work for all of Function's parents, which is just the one you mentioned.

But no, it can be solved without reusing an existing constructor. I don't think defineProperty will help much.

Re: Coding: Fleeting Thoughts

Posted: Wed May 29, 2019 8:41 pm UTC
by DavidSh
In python, both isinstance(type,type) and isinstance(object,object) evaluate to True. You can also set isinstance() for an object to do pretty much anything you want.

Code: Select all

class x(object):
  def __instancecheck__(self,y):
      return True
     
xx = x()

isinstance(xx,xx)
isinstance(3,xx)

Anything is an instance of xx generated in this way.

Re: Coding: Fleeting Thoughts

Posted: Thu May 30, 2019 12:33 am UTC
by phlip
Python2 old-style classes are also just total jank and you can do whatever the hell you want:

Code: Select all

>>> class A:
...   pass
...
>>> A.__class__ = A
>>> isinstance(A, A)
True

Re: Coding: Fleeting Thoughts

Posted: Tue Jun 04, 2019 9:50 am UTC
by Tub
Going to resolve this real quick.

Quoting mdn on instanceof:
The instanceof operator tests whether the prototype property of a constructor appears anywhere in the prototype chain of an object.

For A instanceof A, you need A to
* be a constructor (a function) and an instance
* as a constructor, have a prototype (aka parent class), which is A.__proto__ (nonstandard) or Object.getPrototypeOf(A) (modern)
* as an instance, have that prototype inside of its prototype chain (A.prototype, or further up the chain)

Doing those requirements verbatim, you can do this:

Code: Select all

function A() {}
A.prototype = Object.getPrototypeOf(A);

But then A is just a plain function, not a custom class. If you want your own prototype in there, you'll find that you cannot simultaneously define A as function A() and as A = Object.create(..). But there's Object.setPrototypeOf:

Code: Select all

function A() { };

let proto = { };
Object.setPrototypeOf(A, proto);

A.prototype = Object.getPrototypeOf(A);


In PHP, the trick is a bit different. The operator is defined as [instance] instanceof [class], usually $A instanceof Foo.
[instance] can be a variable $A or a constant A.
[class] can be a class name, or a string variable holding a class name.

Code: Select all

A instanceof A

This might work if A is both a constant and a class name (not sure how PHP resolves the naming conflicts), but constants cannot hold objects, just primitive types. Primitive types are never an instance of any class.

Code: Select all

$A instanceof $A

This works if $A is an object of our class, and a string holding the name of our class. Remembering that strings are primitive types, not objects, can this be done? Thanks to type coercion, it can.

Code: Select all

class Foo {
   public function __toString() {
      return 'Foo';
   }
};

$A = new Foo();

echo ($A instanceof $A) ? 'yes' : 'no';