<!DOCTYPE html>
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
  </head>
  <body>
    <p><br>
    </p>
    <div class="moz-cite-prefix">On 26/10/2025 13:56, Nir Lisker wrote:<br>
    </div>
    <blockquote type="cite"
cite="mid:CA+0ynh9NHeF=-7tLyGjtj6BbK-VVe8UtoR3deKGkxjTf29d=XQ@mail.gmail.com">
      <meta http-equiv="content-type" content="text/html; charset=UTF-8">
      <div dir="ltr"><br>
        <div style="padding:0px 2px">Some observations:</div>
        <div style="padding:0px 2px">Bindings returns a Binding rather
          than an ObservableValue and also has primitive specialization
          versions that have their unique methods (add, subtract...).
          These methods, however, can be replicated with fluent bindings
          and they also have the "known" subtle GC issue for the
          intermediary values.</div>
      </div>
    </blockquote>
    <p>The subtle GC is rather easy to hit I saw.</p>
    <p>I often write code that has very little assignments, and operates
      by using listeners/subscriptions, and this code is already
      incorrect:</p>
    <div style="background-color:#ffffff;padding:0px 0px 0px 2px;">
      <div
style="color:#000000;background-color:#ffffff;font-family:"Consolas";font-size:11pt;white-space:pre;"><p
      style="margin:0;"><span style="color:#000000;">    // All local variables:
    ObjectProperty<LocalDate> departureDate = </span><span
      style="color:#0000a0;font-weight:bold;">new</span><span
      style="color:#000000;"> SimpleObjectProperty<>();</span></p><p
      style="margin:0;"><span style="color:#000000;">    ObjectProperty<LocalDate> returnDate = </span><span
      style="color:#0000a0;font-weight:bold;">new</span><span
      style="color:#000000;"> SimpleObjectProperty<>();</span></p><p
      style="margin:0;"><span style="color:#000000;">    ObservableValue<Boolean> returnTrip = tripType.map(v -> v.equals(</span><span
      style="color:#2a00ff;">"Return"</span><span style="color:#000000;">));</span></p><p
      style="margin:0;"><span style="color:#000000;">    BooleanBinding datesValid = Bindings.</span><span
      style="color:#000000;font-style:italic;">createBooleanBinding</span><span
      style="color:#000000;">(() -> {</span></p><p style="margin:0;"><span
      style="color:#000000;">      </span><span
      style="color:#7f0055;font-weight:bold;">return</span><span
      style="color:#000000;"> returnTrip.getValue() && departureDate.get() != </span><span
      style="color:#0000a0;font-weight:bold;">null</span><span
      style="color:#000000;"> && returnDate.get() != </span><span
      style="color:#0000a0;font-weight:bold;">null</span><span
      style="color:#000000;"> ? departureDate.get().compareTo(returnDate.get()) < 0 : </span><span
      style="color:#0000a0;font-weight:bold;">false</span><span
      style="color:#000000;">;</span></p><p style="margin:0;"><span
      style="color:#000000;">    }, departureDate, returnDate, returnTrip);</span></p><p
      style="margin:0;">
    ... create some UI where dp is a DatePicker ...
 
</p><div style="background-color:#ffffff;padding:0px 0px 0px 2px;"><div
style="color:#000000;background-color:#ffffff;font-family:"Consolas";font-size:11pt;white-space:pre;"><p
      style="margin:0;"><span style="color:#000000;">    datesValid.subscribe(valid -> {</span></p><span
      style="color:#000000;">      </span><span
      style="color:#0000a0;font-weight:bold;">if</span><span
      style="color:#000000;"> (valid) {</span><p style="margin:0;"><span
      style="color:#000000;">        dp.getStyleClass().remove(</span><span
      style="color:#2a00ff;">"invalid"</span><span
      style="color:#000000;">);</span></p><p style="margin:0;"><span
      style="color:#000000;">      }</span></p><p style="margin:0;"><span
      style="color:#000000;">      </span><span
      style="color:#0000a0;font-weight:bold;">else</span><span
      style="color:#000000;"> {</span></p><p style="margin:0;"><span
      style="color:#000000;">        dp.getStyleClass().add(</span><span
      style="color:#2a00ff;">"invalid"</span><span
      style="color:#000000;">);</span></p><p style="margin:0;"><span
      style="color:#000000;">      }</span></p><p style="margin:0;"><span
      style="color:#000000;">    });</span></p></div></div></div>
    </div>
    <p></p>
    <p>It works perfectly, even for a longer period, until I added a few
      `System.gc()` calls, and the binding just poofs despite having a
      subscription on it.</p>
    <p>It's really disingenious, nothing is mentioned in the docs that
      the above is incorrect usage:</p>
    <p>- Not in Bingdings#createBooleanBinding<br>
      - Not in BooleanBinding<br>
      - Not in Binding</p>
    <p>The only thing mentioned is that you can use `unbind` to stop
      observing (or just wait for a random GC to occur obviously...)<br>
      <br>
      --John<br>
    </p>
    <p><br>
    </p>
    <blockquote type="cite"
cite="mid:CA+0ynh9NHeF=-7tLyGjtj6BbK-VVe8UtoR3deKGkxjTf29d=XQ@mail.gmail.com">
      <div dir="ltr">
        <div style="padding:0px 2px"><br>
        </div>
        <div style="padding:0px 2px">The proposal is more ergonomic
          with its fluency for a couple of values, but I'm not sure it
          solves enough problems that the current mechanism can't.</div>
      </div>
      <br>
      <div class="gmail_quote gmail_quote_container">
        <div dir="ltr" class="gmail_attr">On Sun, Oct 26, 2025 at
          11:59 AM John Hendrikx <<a
            href="mailto:john.hendrikx@gmail.com" moz-do-not-send="true"
            class="moz-txt-link-freetext">john.hendrikx@gmail.com</a>>
          wrote:<br>
        </div>
        <blockquote class="gmail_quote"
style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">JEP:
          <a
href="https://gist.github.com/hjohn/611acb65769b68a845b8919c62a3e99a"
            rel="noreferrer" target="_blank" moz-do-not-send="true"
            class="moz-txt-link-freetext">https://gist.github.com/hjohn/611acb65769b68a845b8919c62a3e99a</a><br>
          <br>
          Hi everyone,<br>
          <br>
          I'd like to propose an extension to the fluent bindings API on<br>
          ObservableValue (map, flatMap, orElse) which were introduced
          in JavaFX<br>
          19 over 3 years ago.<br>
          <br>
          The API currently is very powerful when dealing with a single<br>
          observable, but lacks support when dealing with multiple
          observables. <br>
          For example, let's say you want to compute a width/height
          ratio.  You<br>
          could write this:<br>
          <br>
              ObservableValue<Double> ratio = width.map(w -> w
          / height.get());<br>
          <br>
          ... but you'll quickly find that such an observable will not
          update<br>
          itself when height changes, only when width changes.<br>
          <br>
          The go-to solution for this is currently:<br>
          <br>
              DoubleBinding ratio = new DoubleBinding() {<br>
                  { bind(width, height); }<br>
          <br>
                  protected double computeValue() { return width.get() /<br>
          height.get(); }<br>
              }<br>
          <br>
          My proposal would extend ObservableValue with a new `with`
          method that<br>
          returns an intermediate stage that can be easily converted
          back to an<br>
          ObservableValue:<br>
          <br>
              ObservableValue<Double> ratio =
          width.with(height).map((w, h) -> w /<br>
          h);  // yields a ratio that updates whenever w or h changes<br>
          <br>
          Or for example:<br>
          <br>
               ObservableValue<Point> point =
          x.with(y).map(Point::new);  //<br>
          yields a Point that updates whenever x or y changes<br>
          <br>
          The intermediate stage would not be an observable value
          itself.  This<br>
          limits the API surface, and makes this proposal fairly
          lightweight and<br>
          much easier to implement.<br>
          <br>
          Please see the JEP for the full proposal.  I look forward to
          your feedback!<br>
          <br>
          --John<br>
          <br>
          <br>
        </blockquote>
      </div>
    </blockquote>
  </body>
</html>