[Info-vax] BASIC (and Horizon)
Dave Froble
davef at tsoft-inc.com
Wed Jan 31 23:00:35 EST 2024
On 1/31/2024 7:29 PM, Arne Vajhøj wrote:
> On 1/31/2024 6:21 PM, Lawrence D'Oliveiro wrote:
>> On Wed, 31 Jan 2024 17:08:44 -0500, Arne Vajhøj wrote:
>>
>>> On 1/31/2024 4:28 PM, Lawrence D'Oliveiro wrote:
>>>
>>>> I have never written a goto in C code (not production code, anyway). These
>>>> days, you need to do so much dynamic allocation, there is nearly always
>>>> some need for cleanup when exiting an inner block anyway, so you can’t
>>>> just jump directly somewhere else first. The overall pattern looks like
>>>> this:
>>>>
>>>> MyPtr obj = NULL;
>>>> do /*once*/
>>>> {
>>>> ... possible other stuff ...
>>>> «allocate memory for obj»;
>>>> if («error occurred»)
>>>> break;
>>>> ... possible other stuff using obj ...
>>>> }
>>>> while (false);
>>>> free(obj);
>>>>
>>>> You can confirm, just by inspection, that there is no path out of the
>>>> block that does not pass through the free() call precisely once.
>>>
>>> And the difference compared to:
>>>
>>> MyPtr obj = NULL;
>>> ... possible other stuff ...
>>> «allocate memory for obj»;
>>> if («error occurred»)
>>> goto lbl_freeobj;
>>> ... possible other stuff using obj ...
>>> lbl_freeobj:
>>> free(obj);
>>>
>>> are?
>>
>> Nesting.
>
> Goto work fine with nested loops. In fact it is one of the cases
> where it really makes sense.
>
>> Try to scale up to something like
>>
>> static PyObject * discipline_makedict
>> (
>> PyObject * self,
>> PyObject * args
>> )
>> {
>> PyObject * result = NULL;
>> PyObject * tempresult = NULL;
>> br_PyObject * items;
>> const br_char * msg = NULL;
>> do /*once*/
>> {
>> const bool parsed_ok = PyArg_ParseTuple(args, "Os", &items, &msg);
>> if (not parsed_ok)
>> break;
>> fprintf(stdout, "makedict says: “%s”\n", msg);
>> if (not PyTuple_Check(items))
>> {
>> PyErr_SetString(PyExc_TypeError, "expecting a tuple");
>> break;
>> } /*if*/
>> const ssize_t nr_items = PyTuple_Size(items);
>> if (PyErr_Occurred())
>> break;
>> tempresult = PyDict_New();
>> if (tempresult == NULL)
>> break;
>> for (ssize_t i = 0;;)
>> {
>> if (i == nr_items)
>> break;
>> br_PyObject * const item = PyTuple_GetItem(items, i);
>> if (item == NULL)
>> break;
>> if (not PyTuple_Check(item) or PyTuple_Size(item) != 2)
>> {
>> PyErr_SetString(PyExc_TypeError, "expecting a 2-tuple");
>> break;
>> } /*if*/
>> br_PyObject * const first = PyTuple_GetItem(item, 0);
>> if (first == NULL)
>> break;
>> br_PyObject * const second = PyTuple_GetItem(item, 1);
>> if (second == NULL)
>> break;
>> if (first == (PyObject *)&ExceptMe_type or second == (PyObject
>> *)&ExceptMe_type)
>> {
>> PyErr_SetString(PyExc_ValueError, "ExceptMe object found");
>> break;
>> } /*if*/
>> if (PyDict_SetItem(tempresult, first, second) < 0)
>> break;
>> ++i;
>> } /*for*/
>> if (PyErr_Occurred())
>> break;
>> /* all done */
>> result = tempresult;
>> tempresult = NULL; /* so I don’t dispose of it yet */
>> }
>> while (false);
>> Py_XDECREF(tempresult);
>> return
>> result;
>> } /*discipline_makedict*/
>
> That code would look a lot cleaner if the do while(false) loop got
> removed and the relevant breaks got replaced by goto's.
>
> A well named goto label is much more informative than a plain break.
>
>> More details here
>> <https://gitlab.com/ldo/a_structured_discipline_of_programming/>.
>
> Truly bad design.
>
> All the code examples would look better with the do while(false) loops
> removed and appropriate goto's.
>
> Arne
>
It's called do whatever to avoid a goto, and it can be very bad ...
--
David Froble Tel: 724-529-0450
Dave Froble Enterprises, Inc. E-Mail: davef at tsoft-inc.com
DFE Ultralights, Inc.
170 Grimplin Road
Vanderbilt, PA 15486
More information about the Info-vax
mailing list