Microsoft MakeCode

Don't understand "enum emitted as constants for drop-downs"

Can anyone please help explain this? The reference doesn’t appear to make enough sense to me.

I have a main.ts for a game and an extension defining an extension in a namespace. Here is what is in the extension.ts:

//% emitAsConstant
enum Plots {
    //% block="line"
    Line = 0,
    //% block="box"
    Box = 1,
    //% block="rectangle"
    Rect = 2
}
//% enumIdentity="Plots.Line"
const LINE = Plots.Line;
//% enumIdentity="Plots.Box"
const BOX = Plots.Box;
//% enumIdentity="Plots.Rect"
const RECT = Plots.Rect;

namespace myscrollbit {
    ....blah blah....
    //% blockId=myscrollbit_plot
    //% block="plot %plot from x %x0 y %y0 to x %x1 y %y1"
    export function plot(plot: Plots, x0: number, y0: number, x1: number, y1: number): void {
        blah blah
    }
}

And then in the main.ts if I place a “plot box…” block and then switch to Javascript view, the code appears as:

myscrollbit.plot(Plots.Box, p, q, x, y)

But I thought the idea of “emitting as a constant” would mean that the drop-down list would assume one of LINE, RECT, BOX rather than one of Plots.Line, Plots.Rect, Plots.Box. In the Reference is a section on this which includes the phrase " If the enum has a shim function, you can also set blockIdentity just like you can for enum members." but it’s not at all clear to me what I’m supposed to make of that. Is it supposed to make the drop-down assuming the LINE/RECT/BOX constants, or not?

To clarify, are you using beta or the live site? This feature was only added in January, so it won’t work on the live site quite yet.

I’m using live.

Oh, and I also want to be able to place a variable in the Block field for a similar block with a similar enum as a drop-down field - eg using a variable to determine whether it’s line/box/rect - . But that is only possible if you define a function along the lines of the following, and then place “%plots=plot_conv” in the block annotations for myscrollbit.plot().

//% blockId="plot_conv" block="%plot"
//% blockHidden=true
export function pl(plot: Plots): number {
    switch (plot) {
        case Plots.Line: return 0;
        case Plots.Box: return 1;
        case Plots.Rect: return 2;
        default: return 0;
    }
}

The problem then is you get a horribly verbose Javascript function in the main.ts when you’re relying on the drop-down list:

myscrollbit.plot(myscrollbit.pl(Plots.Line))

Is that unavoidable?

I have to say that for a relative newcomer to this, I find the Reference page on Defining Blocks not at all clear in some instances.

emitAsConstant will definitely not work until next full release / update.

I believe you wanna mark pl as //% shim=TD_ID to indicate it is just a wrapper for blocks that shouldn’t be emitted, and you can just have the body be return plot || 0 instead of doing the switch on values (as it’s written it’s basically if plot == 2 return 2 and so on).

If you have specific cases of things not being easy to parse in the docs on defining blocks we can take a look at them, but a lot of it comes down to there just being a lot of options that get added over time. That page is kept up to date in relation to the latest branch of pxt, and not versioned to any specific targets, so as new features are added / bugs are fixed they may not be fully usable in any given target yet.

As a side note, it’s typically easiest to help if you can give a share link to the code you’re working on / a working version, so we can sanity check things / give back a version with the changes.

Thank you very much. I had read the bit in the Reference about shim=TD_ID but unfortunately I see no explanation of what TD_ID means. I thought I had tried adding the shim to pl() earlier but I had something else different which didn’t help, and it got all mixed up. I’ve deleted the emitAsConstant for now.

Now I’ve got it. I think. The following is the relevant parts of extension code. I have two functions plot() and scrollDisplay() which have enumerated drop-down lists. In block-view I can now either use the drop-down list or I can insert a variable to select up/down/left/right for scrollDisplay(), but just the drop-down list for line/box/rect in plot() because the %plot field is typed as a Plots not a number, unlike for scrollDisplay().

In Javascript view this gives a sensible line such as myscrollbit.scrollDisplay(Scrolls.Up) or myscrollbit.scrollDisplay(myDirectionVariable) which is what I wanted. Phew!

enum Scrolls {
    //% block="Up"
    Up = 0,
    //% block="Right"
    Right = 1,
    //% block="Down"
    Down = 2,
    //% block="Left"
    Left = 3
}
enum Plots {
    //% block="line"
    Line = 0,
    //% block="box"
    Box = 1,
    //% block="rectangle"
    Rect = 2
}
namespace myscrollbit {
    //% shim=TD_ID
    //% blockId="dir_conv" block="%dir"
    export function dirs(dir: Scrolls): number {  return (dir || 0) }
    //% shim=TD_ID
    //% blockId="plot_conv" block="%plot"
    export function pl(plot: Plots): number { return (plot || 0)  }
    //% blockId=myscrollbit_plot
    //% block="plot %plot=plot_conv from x %x0 y %y0 to x %x1 y %y1 $state"
    //% state.shadow="toggleOnOff"
    //% state.defl=true
    //% inlineInputMode=inline
    //% blockGap=8
    export function plot(plot: Plots, x0: number, y0: number, x1: number, y1: number, state: boolean): void {
        blah blah
    }
    //% blockId=myscrollbit_scroll
    //% block="scroll scroll:bit %direction=dir_conv"
    export function scrollDisplay(direction: number): void {
        blah blah
    }
}

Ahh, sounds good. To be honest, I don’t remember exactly what the shim stands for, I might have never asked hah – I know ID refers to identity (as in an identity function), so I was always thinking of it standing for TypeScript Decompile Identity shim.

Glad it works for you, and when the next release occurs it’s an easy / nonbreaking thing to upgrade if you want

TD_ID … TouchDevelop_Identity function…

1 Like

Ahh that would have been my second guess